Unable to set public properties on instance of C# Class - c#

I'm trying try to write my first NSpec test in a Mobile Service application. I created an attribute in the spec. But when I try to access that element on the next line I can't access the public properties on the instance because Visual Studio is not recognizing the variable.
AppointmentSpec.cs
public class AppointmentSpec : nspec
{
private AppointmentDTO _dto = new AppointmentDTO();
_dto.PatientId = "124234"; // Visual Studio is not regonizing _dto
}
AppointmentDTO.cs
public class AppointmentDTO
{
public string PatientId { get; set; }
// public string PathwayId { get; set; }
public string ItemId { get; set; }
public string Subject { get; set; } //Dr. Visit, labtest, labtest name, follow up, other...
// public string ProviderName { get; set; }
public string Location { get; set; } //clinic, hsopital name, etc
public string Address { get; set; } //street address
public string PhoneNumber { get; set; }
//to automatically add a corresponding appointment to the provider's calendar
public bool SetProviderAppointment { get; set; }
public string ProviderItemId { get; set; }
public List<string> ProviderItemIds { get; set; }
public bool IsVideoCall { get; set; }
public TimeSpan StartTime { get; set; }
public TimeSpan EndTime { get; set; }
public DateScheduleInfo EventDateSchedule { get; set; }
//public TimeScheduleInfo EventTimeSchedule { get; set; }
//public void Send(object target, string methodName, params object[] args)
//{
// var properties = GetProperties(target.GetType());
// var property = properties.First(p => p.Name == methodName);
// if(property == null)
// throw new ArgumentException($"{target.GetType()} has no property or method ");
// property.SetValue(target, args.First());
//}
//private static IEnumerable<PropertyInfo> GetProperties(Type t)
//{
// return t == null ? Enumerable.Empty<PropertyInfo>() : t.GetProperties().Union(GetProperties(t.BaseType));
//}
}

Do the assignment inside the constructor of the class:
public class AppointmentSpec : nspec
{
private AppointmentDTO _dto = new AppointmentDTO();
public AppointmentSpec()
{
_dto.PatientId = "124234";
}
}

You're accessing _dto in an invalid context. If you meant to initialize PatientId with some data, try this:
private AppointmentDTO _dto = new AppointmentDTO
{
PatientId = "124234"
};
See MSDN

Related

How to loop thru a model and print without typing the name of properties

I have a Model that is filled with 20 Properties, for instance such as
public class SensorModel
{
public string Trigger1 { get; set; }
public string PathDoor1 { get; set; }
public string PathDoor2 { get; set; }
public string PathTrigger1 { get; set; }
public string PathTrigger2 { get; set; }
public string PathTrigger3 { get; set; }
public string PathTrigger4 { get; set; }
public string PathTrigger5 { get; set; }
public string PathTrigger6 { get; set; }
public string PathTrigger7 { get; set; }
public string PathTrigger8 { get; set; }
}
After declaring and setting their properties by doing such,
SensorModel sensorsData = new SensorModel();
How can I access sensorsData's properties using a loop?
Because I would like to logs all the data into a txt along with DateTime, I find manually accessing is a waste of time.
Is there any way to automate, for instance, using a loop and accessing it one by one?
You can use reflection to achieve your goal:
var model = new SensorModel() {
PathDoor1 = "Foo",
PathDoor2 = "Foo2",
PathTrigger1 = "Value of PT1",
PathTrigger2 = "Value of PT2",
};
foreach(var value in model.GetTriggerValues()) {
Console.WriteLine(value);
}
public class SensorModel
{
public string Trigger1 { get; set; }
public string PathDoor1 { get; set; }
public string PathDoor2 { get; set; }
public string PathTrigger1 { get; set; }
public string PathTrigger2 { get; set; }
/* ... */
public IEnumerable<string> GetTriggerValues() {
foreach(var prop in this.GetType().GetProperties().Where(x => x.Name.StartsWith("PathTrigger"))) {
yield return (string)prop.GetValue(this, null);
}
}
}
This example filters your properties by name, if you want or need a different result set, amend or remove the where clause.
You can use reflection to achieve this:
var obj = new SensorModel();
// ...
// Get all the properties of your class
var props = typeof(SensorModel).GetProperties();
foreach (var prop in props)
{
// Get the "Get" method and invoke it
var propValue = prop.GetGetMethod()?.Invoke(obj, null);
// Do something with the value
Console.Out.WriteLine("propValue = {0}", propValue);
}

"Property ID cannot be modified" error when trying to update a different property

This question has been asked before and each time the answer has been that the code WAS updating the Id property on an entity. I cannot see how my code is modifying this property.
System.InvalidOperationException: The property 'Id' is part of the object's key information and cannot be modified.
at System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInProperty(Int32 ordinal, Boolean detectOnlyComplexProperties, Boolean detectOnly)
The above error is thrown on the first line where I set my objects Attempt property to IsModified = true seen below.
private static void SaveDocumentCreationToDatabase(Document document)
{
using (MyEntities context = new MyEntities ())
{
context.Database.Log += (x) => dbSaveLog.Debug($"Document Id: {document.Id}. Message:\r\n{x}");
context.Documents.Attach(document); // state = unchanged
// Set document modified properties
context.Entry(document).Property(u => u.Attempt).IsModified = true; // ERROR THROWN HERE
context.Entry(document).Property(u => u.Result).IsModified = true;
context.Entry(document).Property(u => u.NewId).IsModified = true;
context.Entry(document).Property(u => u.PropertiesUploaded).IsModified = true;
// modify some of the navigation properties ... etc
// Debug
// Inspect Change Tracking on this context
// Output all tracked entities that are added or modified, their key, and their modified properties
string logOfModifiedEntities = GetAllModifiedEnitiesFromContext(document, context);
dbSaveLog.Debug($"{logOfModifiedEntities}");
// End debug
context.SaveChanges();
}
}
The document object looks like this:
public class Document
{
public int Id { get; set; }
// Previous system metadata
public string DocumentKey { get; set; }
public string OldParent { get; set; }
public string OldChild { get; set; }
// Migration metadata
public bool MigrationReady { get; set; }
public int LoadPriortity { get; set; }
public int Attempt { get; set; }
public int Result { get; set; }
public bool PropertiesUploaded { get; set; }
[StringLength(14)]
public string NewId { get; set; }
[ForeignKey("CabinetConfiguration")]
public string Cabinet { get; set; }
public string Name { get; set; }
public string Extension { get; set; }
public bool InheritsSecurity { get; set; }
public virtual ICollection<DocumentVersion> DocumentVersions { get; set; }
public virtual ICollection<DocumentLog> DocumentLogs { get; set; }
[InverseProperty("DocumentParent")]
public virtual ICollection<DocumentLinking> DocumentParents { get; set; }
[InverseProperty("DocumentLink")]
public virtual ICollection<DocumentLinking> DocumentLinks { get; set; }
public virtual CabinetConfiguration CabinetConfiguration { get; set; }
public Document()
{
DocumentVersions = new HashSet<DocumentVersion>();
DocumentLogs = new HashSet<DocumentLog>();
}
}

Map a flatten SQL response to an object containing lists of lists with Automapper

The error message that I'm receiving at runtime is:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the source/destination type
For no matching constructor, add a no-arg ctor, add optional arguments, or map all of the constructor parameters
List'1 -> MobileRoot (Destination member list)
System.Collections.Generic.List'1[[Strata.CS.Jazz.Biz.Dashboard.MobileInfo, Strata.CS.Jazz.Biz, Version=2019.10.0.0, Culture=neutral, PublicKeyToken=null]] -> Strata.Jazz.Web.Controllers.MobileController+MobileRoot (Destination member list)
Unmapped properties:
Users
From what I can tell from the error message is that AutoMapper needs to know how to handle the ForMember Users create in the MobileRoot, and then propagate that for each of the subsequent lists down the chain. Can anyone tell me how to do this efficiently using AutoMapper? I know how to do this with Linq using GroupBy and Select, so it is my thought that this should be do-able with AutoMapper.
The query I have returns this class:
public class MobileInfo
{
public string NameFull { get; set; }
public string EmailAddress { get; set; }
public string SolutionName { get; set; }
public int SortOrder { get; set; }
public string Name { get; set; }
public bool IsLegacy { get; set; }
public string Description { get; set; }
public string WidgetName { get; set; }
public int Row { get; set; }
public int Col { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public string WidgetClassName { get; set; }
public string Data { get; set; }
}
I would like to use Automapper with profiles to have it return this:
internal class MobileRoot
{
public IEnumerable<MobileUser> Users { get; set; }
}
internal class MobileUser
{
public string NameFull { get; set; }
public string EmailAddress { get; set; }
public IEnumerable<MobileSolution> Solutions { get; set; }
}
internal class MobileSolution
{
public string Solution { get; set; } // MobileInfo.SolutionName
public int SortOrder { get; set; }
public IEnumerable<MobileDashboard> Dashboards { get; set; }
}
internal class MobileDashboard
{
public string Dashboard { get; set; } // MobileInfo.Name
public bool IsLegacy { get; set; }
public string Description { get; set; }
public IEnumerable<MobileWidget> Widgets { get; set; }
}
internal class MobileWidget
{
public string Widget { get; set; } // MobileInfo.WidgetName
public int Row { get; set; }
public int Col { get; set; }
public int Height { get; set; }
public int Width { get; set; }
public string WidgetClassName { get; set; }
public string Data { get; set; }
}
The Profiles I have defined so far are:
public class ProfileMobileRoot : Profile
{
public ProfileMobileRoot()
{
CreateMap<MobileInfo, MobileRoot>();
}
}
public class ProfileMobileUser : Profile
{
public ProfileMobileUser()
{
CreateMap<MobileInfo, MobileUser>();
}
}
public class ProfileMobileSolution : Profile
{
public ProfileMobileSolution()
{
CreateMap<MobileInfo, MobileSolution>();
}
}
public class ProfileMobileDashboard : Profile
{
public ProfileMobileDashboard()
{
CreateMap<MobileInfo, MobileRoot>();
}
}
public class ProfileMobileWidget : Profile
{
public ProfileMobileWidget()
{
CreateMap<MobileInfo, MobileWidget>();
}
}
You can do something like below. It's a little late so my solution isn't so sophisticated... but it works ;)
public class ProfileMobileRoot : Profile
{
public ProfileMobileRoot()
{
CreateMap<MobileInfo, MobileWidget>()
.ForMember(x=>x.Name, opt=>opt.MapFrom(x=>x.WidgetName));
CreateMap<IEnumerable<MobileInfo>, IEnumerable<MobileDashboard>>()
.ConvertUsing<DashboardConverter>();
CreateMap<IEnumerable<MobileInfo>, IEnumerable<MobileSolution>>()
.ConvertUsing<SolutionConverter>();
CreateMap<IEnumerable<MobileInfo>, IEnumerable<MobileUser>>()
.ConvertUsing<UserConverter>();
CreateMap<IEnumerable<MobileInfo>, MobileRoot>()
.ForMember(x => x.Users, opt => opt.MapFrom(x => x.ToList()));
}
}
class UserConverter : ITypeConverter<IEnumerable<MobileInfo>, IEnumerable<MobileUser>>
{
public IEnumerable<MobileUser> Convert(IEnumerable<MobileInfo> source, IEnumerable<MobileUser> destination, ResolutionContext context)
{
var groups = source.GroupBy(x => new { x.NameFull, x.EmailAddress});
foreach (var v in groups)
{
yield return new MobileUser()
{
EmailAddress = v.Key.EmailAddress,
NameFull = v.Key.NameFull,
Solutions = context.Mapper.Map<IEnumerable<MobileSolution>>(source.Where(x =>
v.Key.NameFull == x.NameFull && v.Key.EmailAddress== x.EmailAddress)).ToList()
};
}
}
}
class SolutionConverter : ITypeConverter<IEnumerable<MobileInfo>, IEnumerable<MobileSolution>>
{
public IEnumerable<MobileSolution> Convert(IEnumerable<MobileInfo> source, IEnumerable<MobileSolution> destination, ResolutionContext context)
{
var groups = source.GroupBy(x => new { x.SolutionName, x.SortOrder});
foreach (var v in groups)
{
yield return new MobileSolution()
{
Solution = v.Key.SolutionName,
SortOrder = v.Key.SortOrder,
Dashboards= context.Mapper.Map<IEnumerable<MobileDashboard>>(source.Where(x =>
v.Key.SolutionName== x.SolutionName&& v.Key.SortOrder== x.SortOrder)).ToList()
};
}
}
}
class DashboardConverter : ITypeConverter<IEnumerable<MobileInfo>, IEnumerable<MobileDashboard>>
{
public IEnumerable<MobileDashboard> Convert(IEnumerable<MobileInfo> source, IEnumerable<MobileDashboard> destination, ResolutionContext context)
{
var groups = source.GroupBy(x => new {x.Name, x.IsLegacy, x.Description});
foreach (var v in groups)
{
yield return new MobileDashboard()
{
Dashboard = v.Key.Name,
Description = v.Key.Description,
IsLegacy = v.Key.IsLegacy,
Widgets = context.Mapper.Map<IEnumerable<MobileWidget>>(source.Where(x =>
v.Key.IsLegacy == x.IsLegacy && v.Key.Name == x.Name && v.Key.Description == x.Description))
};
}
}
}

How to cast an object into type of another variable in C#

I'm working on an entity framework project and I'm trying to form a generic structure for adding joins to my table.
class BrowseCONTACTS_BASE : MyBrowseFrm<CONTACTS_BASE>
{
public BrowseCONTACTS_BASE()
{
MyInitialize();
}
public void MyInitialize()
{
//Here I may have more joins
MyAddJoins<ORDERS>("CONTACTS_BASE", "CB_REFNO", "ORDERS", "OR_REFNO", "OR_REFNO");
}
}
On the parent class MyBrowseFrm
partial class MyBrowseFrm<TEntity>:Form where TEntity:class
{
}
I have the following:
MyAddJoins Function that I call from the child class above
protected void MyAddJoins<TTable>(string pParent, string pParentKey, string pChild, string pChildKey,
string pDisplayField) where TTable:class, new()
{
var a = new TTable();
var item = new MyJoins<dynamic>
{
Parent = pParent,
Child = pChild,
ParentKey = pParentKey,
ChildKey = pChildKey,
DisplayField = pDisplayField,
ChildTable = a
};
MyBdJoins.Add(item);
}
//A list to store Joins added from the child table
private List<MyJoins<dynamic>> MyBdJoins;
protected struct MyJoins<TTable> where TTable : class
{
public string Parent;
public string ParentKey;
public string Child;
public string ChildKey;
public string DisplayField;
public TTable ChildTable;
}
Ok this is the part where I'm stuck, The following code will run when I press the search button.
private void MyGenerateQuery()
{
//Here I cast my Context to CONTACTS_BASE
var loContext = (DbSet<TEntity>)Context.GetPropValue(boName);
foreach (var join in MyBdJoins)
{
loContext
.Join(
(DbSet<ORDERS>)Context.GetPropValue(join.Child),
par => par.GetPropValue(join.ParentKey),
chld => chld.GetPropValue(join.ChildKey),
(par, chld) => new { GetPropValue = chld.GetPropValue(join.DisplayField) }
);
}
myGridView1.DataSource = loContext.ToList();
}
The code above at the part where it is:
(DbSet<ORDERS>)Context.GetPropValue(join.Child)
Here what I want to do is:
(DbSet<TTable>)Context.GetPropValue(join.Child)
of course, the above code gives me an error.
Note: in my code TEntity is CONTACTS_BASE and TTable is ORDERS
so how do I cast this object to type TTable
where it is in MyJoins Structure
public TTable ChildTable;
EDIT:
public partial class ORDERS
{
public int OR_REFNO { get; set; }
public string OR_PROD_CODE { get; set; }
public Nullable<DateTime> OR_DATE { get; set; }
public Nullable<int> OR_M_REFNO { get; set; }
public virtual CONTACTS_BASE CONTACTS_BASE { get; set; }
public virtual ORDER_TYPES ORDER_TYPES { get; set; }
}
public partial class CONTACTS_BASE
{
[SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public CONTACTS_BASE()
{
this.ORDERS = new List<ORDERS>();
}
public int CB_REFNO { get; set; }
public string CB_NAME { get; set; }
public string CB_ID_NO { get; set; }
public string CB_AGE { get; set; }
public Nullable<decimal> CB_TEL_NO { get; set; }
public string CB_EMAIL { get; set; }
public Nullable<DateTime> CB_ENROLL_DATE { get; set; }
public Nullable<DateTime> CB_START_DATE { get; set; }
public Nullable<DateTime> CB_END_DATE { get; set; }
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual IList<ORDERS> ORDERS { get; set; }
}

Set Properties within base function and call function in child function inheritance

I am trying to refactor some old code and wanted to create more logical inheritance.
We have struct Custom Class which we have separated into (3) levels:
AccountView > Details > Full with inheritance. We set the properties of each one as needed.
After looking at the setters, we wanted to combine them into a single class 'SetAccountProp' with methods that set the properties.
We have the 'CustomerBaseView' where we pass in Models ACCOUNT data which works.
Now for the CustomerDetailView pass the same Model ACCOUNT data, but we would like to fill the properties of 'CustomerBaseView' use function 'CustomerBaseView' then fill the details.
Also, for CustomerFullView pass the Model ACCOUNT data, and fill the properties of 'CustomerBaseView' THEN 'CustomerBaseView' and then the remaining fields for CustomerFullView.
How can I call and fill the 'CustomerBaseView' within the 'CustomerDetailView' function? Do I initialize new AccountsView(); in each function?
Not sure how to finish up the refactor without repeating the:
// -- CustomView <--- replace with func?
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
in the Details and Full functions.
CODE
namespace BLL.Presenters
{
public class AccountsView
{
public string Email { get; set; }
public bool Active { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Details : AccountsView
{
public bool Administrator { get; set; }
public DateTime? LastLogin { get; set; }
}
public class Full : Details
{
public Guid ID { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public string FullName { get; set; }
}
public class SetAccountProp
{
public static AccountsView CustomerBaseView(Account data)
{
var view = new AccountsView();
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
return view;
}
public static Details CustomerDetailView(Account data)
{
var view = new Details();
// -- CustomView <--- replace with func?
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
// -- Details
view.Administrator = data.Administrator;
view.LastLogin = data.LastLogin;
return view;
}
public static Full CustomerFullView(Account data)
{
var view = new Full();
// -- CustomView <--- replace with func?
view.Email = data.Email;
view.Active = data.Active;
view.FirstName = data.FirstName;
view.LastName = data.LastName;
// -- Details <--- replace with func?
view.Administrator = data.Administrator;
view.LastLogin = data.LastLogin;
// -- Full
view.ID = data.ID;
view.Created = data.Created;
view.Modified = data.Modified;
view.FullName = data.LastName + ", " + data.FirstName;
return view;
}
}
}
Using constructor chaining, you could have something like this:
Each constructor calls it's base class' constructor first, so you don't have to repeat code.
namespace BLL.Presenters
{
using System;
public class Account // dummy to make it compile
{
public string Email;
public bool Active;
public string FirstName;
public string LastName;
public bool Administrator;
public DateTime? LastLogin;
public Guid ID;
public DateTime Created;
public DateTime Modified;
}
public class AccountsView
{
public string Email { get; set; }
public bool Active { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public AccountsView(Account data)
{
this.Email = data.Email;
this.Active = data.Active;
this.FirstName = data.FirstName;
this.LastName = data.LastName;
}
}
public class Details : AccountsView
{
public bool Administrator { get; set; }
public DateTime? LastLogin { get; set; }
public Details(Account data) : base(data)
{
this.Administrator = data.Administrator;
this.LastLogin = data.LastLogin;
}
}
public class Full : Details
{
public Guid ID { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public string FullName { get; set; }
public Full(Account data) : base(data)
{
this.ID = data.ID;
this.Created = data.Created;
this.Modified = data.Modified;
this.FullName = data.LastName + ", " + data.FirstName;
}
}
class Program
{
static void Main()
{
Console.WriteLine();
Console.ReadLine();
}
}
}
Why not something like this:
public class CustomerBase
{
public string Email { get; private set; }
public bool Active { get; private set; }
public string FirstName { get; private set; }
public string LastName { get; private set; }
protected void SetAccountInfo(Account account)
{
this.Email = account.Email;
this.Active = account.Active;
this.FirstName = account.FirstName;
this.LastName = account.LastName;
}
}
public class CustomerA : CustomerBase
{
public string IsAdmin { get; private set; }
public DateTime? LastLogin { get; private set; }
public void SetAccountInfo(Account account)
{
base.SetAccountInfo(account);
this.IsAdmin = account.IsAdmin;
this.LastLogin = account.LastLogin;
}
}
public class Account
{
//your properties
public string Email { get; set; }
public bool Active { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string IsAdmin { get; set; }
public DateTime? LastLogin { get; set; }
}
Or let the SetAccountInfo() return this
public CustomerA SetAccountInfo(Account account)
{
base.SetAccountInfo(account);
this.IsAdmin = account.IsAdmin;
this.LastLogin = account.LastLogin;
return this;
}

Categories

Resources