I'm sorry if it's a dumb question, but i just can't seem to get a grip.
I got 2 classes, Customer and Member.
Customer.cs
public class Customer
{
public virtual string Firstname { get; set; }
public virtual string Middlename { get; set; }
public virtual string Lastname { get; set; }
}
Member.cs
public class Member : Customer
{
public virtual string MemberId { get; set; }
public virtual string MemberRegistrationDate { get; set; }
public virtual string MembershipStatus { get; set; }
public Member()
{
MemberRegistrationDate = DateTime.Now;
MembershipStatus = MembershipStatusEnum.Active;
}
}
I'm pretty sure this has to be an inheritance, in which Member is a Customer, though if I'm being desperate I can resort to composition.
Note that here I'm using NHibernate that forces me to use all that virtuals.
Given a single customer object, how should a new Member from an existing Customer ?
I can think of 2 options here :
1 - Using Member.cs constructors to recreate it's parents properties
Is this a good thing to do? I tried to do this :
public class Member : Customer
{
public virtual string MemberId { get; set; }
public virtual string MemberRegistrationDate { get; set; }
public virtual string MembershipStatus { get; set; }
public Member(Customer customer)
{
Firstname = customer.Firstname;
Middlename = customer.Middlename;
Lastname = customer.Lastname;
MemberRegistrationDate = DateTime.Now;
MembershipStatus = MembershipStatusEnum.Active;
}
}
But Resharper warns me about accessing virtual member in a constructor, which I do agree to avoid, and tells me to make Member a sealed class which cannot have virtual members (no NHibernate compatibility).
It also raises another issue when someday I added a new property to Customer class, and I forgot to do the same to Member constructor.
2 - Using some sort of reflection helper to map between two objects.
Sure it's a viable option, but I'm currently learning about DDD and I'm wondering if it's okay to put such helper in the domain layer?
Need some suggestions, thanks !
Not sure if I get you right, but there's no need to do anything Customer related in your Member class. You only need to tell NHibernate that Member derives from Customer, and you need to provide the correct mapping for both classes. That's it, the rest goes automatically (that's the whole point of inheritance in OOP, anyway).
Regarding your second issue ('Don't call virtuals in c'tor.'): That's theoretically true, but only relevant if there's a chance that the virtual method gets overwritten in a derived class. So you could safely ignore the R# warning here.
But I think it's cleanest here to get rid of the Member c'tor altogether and declare the class like so:
public class Member : Customer
{
private memberRegistrationDate = DateTime.Now;
private membershipStatus = MembershipStatusEnum.Active;
public virtual string MemberId { get; set; }
public virtual string MemberRegistrationDate
{
get { return this.memberRegistrationDate; };
set { this.memberRegistrationDate = value; };
}
public virtual string MembershipStatus
{
get { return this.membershipStatus; };
set { this.membershipStatus = value; };
}
}
EDIT:
If you're looking for an easy way to turn a customer, into a member, you should maybe entirely keep the conversion code away from your classes and put it into an extension method instead (to keep things clean):
public static class CustomerExtensions
{
public static Member ToMember(this Customer customer)
{
var member = new Member();
member.Firstname = customer.Firstname;
member.Middlename = customer.Middlename;
member.Lastname = customer.Lastname;
return member;
}
}
You can call it then like this:
Member member = customer.ToMember();
Related
I have a few EF model classes that I want to create. Each class has a few common properties that I want to set before inserting a new entity, for example:
public partial class BlogPost {
public DateTime CreatedTime { get; set; }
public string CreatorName { get; set; }
public string PostTitle { get; set; }
public string PostText { get; set; }
}
public partial class Comment {
public DateTime CreatedTime { get; set; }
public string CreatorName { get; set; }
public string CommentText { get; set; }
}
...
When I create these classes, I'm instantiating them like so:
var blogPost = new BlogPost {
CreatedTime = DateTime.UtcNow,
CreatorName = creatorName,
PostTitle = postTitle,
PostText = postText,
};
var comment = new Comment {
CreatedTime = DateTime.UtcNow,
CreatorName = creatorName,
...
};
...
I want to create a method to automatically set some of the common properties so I don't need to manually type them out for each class with the same properties. Since they don't extend the same class or implement the same interface, I'm wondering how this can be achieved. My first thought was to use a generic method; however, I don't know if there's a way to specify what properties the generic type should have without them extending the same class (similar to TypeScript's "duck typing"). My desired method looks something like this:
public void SetInitialProperties<T>(T dbEntity, DateTime createdTime, string creatorName) where T : ??? {
dbEntity.CreatedTime = createdTime;
dbEntity.CreatorName = creatorName;
}
...
var blogPost = new BlogPost { PostTitle = postTitle, PostText = postText };
SetInitialProperties(blogPost, createdTime, creatorName);
Worst case scenario if I can't use a generic, I could always use dynamic; however, I'd like to keep type checking if possible.
You can achieve what you want using reflection. You can pass in an object and resolve it's type, then get all the public properties of that given type and find if you have one called CreatedTime for example. Then you can set the value of the given property on the passed dbEntity object. However, I do not recommend this solution:
public void SetInitialProperties(object dbEntity, DateTime createdTime, string creatorName) {
// get the passed object's properties and find the one called CreatedTime
var createdTimePropertyInfo = dbEntity.GetType().GetProperties().Where(i => i.Name == "CreatedTime").FirstOrDefault();
// below line is equal to: dbEntity.CreatedTime = createdTime;
createdTimePropertyInfo.SetValue(dbEntity, createdTime);
var creatorNamePropertyInfo = dbEntity.GetType().GetProperties().Where(i => i.Name == "CreatorName").FirstOrDefault();
creatorNamePropertyInfo.SetValue(dbEntity, creatorName);
}
You would be better off on the long run by creating a common interface or even an abstract base class so you don't have to implement CreatedTime and CreatorName and other properties for every EF model. It would look like the following:
public interface IUserEntry
{
DateTime CreatedTime { get; set; }
string CreatorName { get; set; }
}
public abstract class UserEntryBase : IUserEntry
{
public DateTime CreatedTime { get; set; }
public string CreatorName { get; set; }
}
public partial class BlogPost : UserEntryBase
{
public string PostTitle { get; set; }
public string PostText { get; set; }
}
public partial class Comment : UserEntryBase
{
public string CommentText { get; set; }
}
And your SetInitialProperties would be pretty simple:
public void SetInitialProperties(IUserEntry dbEntity, DateTime createdTime, string creatorName)
{
dbEntity.CreatedTime = createdTime;
dbEntity.CreatorName = creatorName;
}
Once you develop onto an interface, you achieve much more flexibility than by using reflection or a dynamic type, since you get the compile-time checking that was mentioned before me and you can see the common properties of your models.
You can't do that in C# because C# uses a nominal type system and not a structural type system.
For your particular case you have to come up with an interface that contains the properties in common and which will be implemented by both entities, then use that new interface as you generic function parameter constraint.
If you're absolutely sure the properties will have the same name, you could pass a dynamic to set property values. However, this prevents any compile-time checking of the typing, so if you accidently pass an incompatible type it won't be caught until runtime.
public void SetInitialProperties(dynamic dbEntity, DateTime createdTime, string creatorName) {
dbEntity.CreatedTime = createdTime;
dbEntity.CreatorName = creatorName;
}
I have created a class and I'm putting a list of same type as a property of that class.
Is it good or bad practice?
I am putting the same type of list because of I want to manage everything by only one object.
I don't want to create a single object and a list of object of the same type.
Any help is highly appreciated!
class AssetSection
{
public string Code { get; set; }
public string Description { get; set; }
public string SITEID { get; set; }
public string PlantID { get; set; }
public string User { get; set; }
public string UpDateTime { get; set; }
public List<AssetSection> AssetSections { get; set; }
public AssetSection(string des, string code)
{
Description = des;
Code = code;
}
}
That's ok. If you can imagine, you can design and use it.
Let's talk about entity framework. We create 2 entities like this:
public class User : IdentityUser
{
[Key]
public string Id { get; set; }
public UserProfile Profile { get; set; }
}
public class UserProfile
{
[Key]
public string UserId { get; set; }
public User User { get; set; }
}
Now, when we try to get current user:
User user = await _userManager.GetUserAsync(User);
user becomes an instance of User class now. This instance has a property name Profile, and this property has another property name User which has a type User.
It's called mapping. So, to answer your question: You can use it. But I'm not saying it's good or not based on the way to design the model.
As a general observation, such a structure is known as a rose tree, or just a tree. It enables you to write code like this:
var t = new AssetSection("foo", "bar")
{
AssetSections = new List<AssetSection>
{
new AssetSection("baz", "qux")
{
new AssetSection("corge", "garply"),
new AssetSection("fred", "plugh")
{
AssetSections = new List<AssetSection>
{
new AssetSection("xyzzy", "thud")
}
}
},
new AssetSection("quux", "quuz")
{
new AssetSection("grault", "waldo")
}
}
};
If what you want to model is a tree-like structure like that, then it's fine. On the other hand, if such a hierarchy is not what you're trying to model, then it's likely to be confusing.
By the way, the code as proposed violates the .NET framework design guidelines:
DO NOT provide settable collection properties.
DO NOT use ArrayList or List<T> in public APIs
I am having trouble understanding the proper use of base and this within an inherited get method. I have an interface IMatchModel:
public interface IMatchModel
{
int TypeId { get; }
DateTime DataDate { get; set; }
string TypeName { get; set; }
}
And a base model class TradeModel:
public class TradeModel
{
public long TradeId { get; set; }
public DateTime DataDate { get; set; }
public string TradeName { get; set; }
}
Then I have a class that inherits from TradeModel and implements IMatchModel. I am currently using the following method:
public class TradeMatchModel : TradeModel, IMatchModel
{
public int TypeId { get { return 1; } }
public string TypeName
{
get
{
return base.TradeName;
}
set
{
base.TradeName = value;
}
}
}
The TradeModel class is used within a function that operates on all of its attributes. IMatchModel is used in a function that only needs the attributes contained in the interface. The code works properly, but I still feel like I don't quite understand if it is best to be using base over this. Is the use of base in this context incorrect?
The only time you need to use base is when you are inside a overridden virtual method and you need to call the base implementation of the method you are currently overriding. All other times you can use this..
Also this. is generally not needed unless you have a name conflict between a field or property in the class and a name of a variable or a parameter. 99% of the time you can just leave off the this. and do return TradeName;
Let's say I have a class from a 3rd-party, which is a data-model. It has perhaps 100 properties (some with public setters and getters, others with public getters but private setters). Let's call this class ContosoEmployeeModel
I want to facade this class with an interface (INavigationItem, which has Name and DBID properties) to allow it to be used in my application (it's a PowerShell provider, but that's not important right now). However, it also needs to be usable as a ContosoEmployeeModel.
My initial implementation looked like this:
public class ContosoEmployeeModel
{
// Note this class is not under my control. I'm supplied
// an instance of it that I have to work with.
public DateTime EmployeeDateOfBirth { get; set; }
// and 99 other properties.
}
public class FacadedEmployeeModel : ContosoEmployeeModel, INavigationItem
{
private ContosoEmployeeModel model;
public FacadedEmployeeModel(ContosoEmployeeModel model)
{
this.model = model;
}
// INavigationItem properties
string INavigationItem.Name { get; set;}
int INavigationItem.DBID { get; set;}
// ContosoEmployeeModel properties
public DateTime EmployeeDateOfBirth
{
get { return this.model.EmployeeDateOfBirth; }
set { this.model.EmployeeDateOfBirth = value; }
}
// And now write 99 more properties that look like this :-(
}
However, it's clear that this will involve writing a huge amount of boilerplate code to expose all the properties , and I'd rather avoid this if I can. I can T4 code-generate this code in a partial class, and will do if there aren't any better ideas, but I though I'd ask here to see if anyone had any better ideas using some super wizzy bit of C# magic
Please note - the API I use to obtain the ContosoEmployeeModel can only return a ContosoEmployeeModel - I can't extend it to return a FacededEmployeeModel, so wrapping the model is the only solution I can think of - I'm happy to be corrected though :)
The other approach may be suitable for you is to use AutoMapper to map base class to your facade here is sample code:
class Program
{
static void Main(string[] args)
{
var model = new Model { Count = 123, Date = DateTime.Now, Name = "Some name" };
Mapper.CreateMap<Model, FacadeForModel>();
var mappedObject = AutoMapper.Mapper.Map<FacadeForModel>(model);
Console.WriteLine(mappedObject);
Console.ReadLine();
}
class Model
{
public string Name { get; set; }
public DateTime Date { get; set; }
public int Count { get; set; }
}
interface INavigationItem
{
int Id { get; set; }
string OtherProp { get; set; }
}
class FacadeForModel : Model, INavigationItem
{
public int Id { get; set; }
public string OtherProp { get; set; }
}
}
Resharper allows the creation of "delegating members", which copies the interface of a contained object onto the containing object and tunnels the method calls/property access through to the contained object.
http://www.jetbrains.com/resharper/webhelp/Code_Generation__Delegating_Members.html
Once you've done that, you can then extract an interface on your proxy class.
I want to propagate the property from child class to parent class,
ie: If MySchool.ModifiedTime is changed it should change the ModifiedTime in Student Class too, like wise LstBook[0].ModifiedTime is changed it should change MySchool.ModifiedTime as well Student.ModifiedTime... (basically ModifiedTime should be in sync),any Idea
I'm looking for a Generic function in BaseClass to achieve this.
public class MyBaseClass
{
public DateTime ModifiedTime{ get; set; }
}
public class Student: MyBaseClass
{
public string Name { get; set; }
public school MySchool {get;set;}
}
public class School : MyBaseClass
{
public string SchoolName { get; set; }
public List<Book> LstBook {get;set;}
}
public class Book:MyBaseClass
{
public string BookName{get;set;}
}
You could make ModifiedTime virtual and then in each child class override it to perform the syncing.
public class MyBaseClass
{
public virtual DateTime ModifiedTime{ get; set; }
}
public class Student: MyBaseClass
{
public string Name { get; set; }
public school MySchool {get;set;}
public virtual DateTime ModifiedTime
{
get {
return MySchool.ModifiedTime;
}
set {
MySchool.ModifiedTime = value;
}
}
}
And so on.
However, I would reconsider your class hierarchy because it seems like the factoring is incorrect. If all the properties need to be in sync across the entire hierarchy then maybe only one class should have that property and other classes should refere to it. For example, only School should have the ModifiedTime property and when you need to get the modified time for a student you would retrieve it through the MySchool property
You seem to be misunderstanding how object hierarchy works.
Implementing this as a class member only links it to the object created, and a static method would of course mean all objects access the same property.
Instead, as I understand it, you want groups of instances (not all) to share a property.
The simplest way to do this is to create a shared object that provides the modified time for all instances in a group.
As the other commenters have pointed out, you can't do this in a straightforward way with a base class simply because that's not how class hierarchies work. What you could do is create another class called "GroupInfo" or something like that. Make ModifiedTime a property on that.
In all your other classes, add a property for a GroupInfo. Then whenever you create a new book or whatever, as part of the constructor pass in a reference to the GroupInfo for the book.
That way all the objects in the group will share a single GroupInfo, and thus a single ModifiedTime.
You can make ModifiedTime static, which will cause it to be shared among all derived instances of MyBaseClass.
public class MyBaseClass
{
public static DateTime ModifiedTime{ get; set; }
}
Update: More complete example; better explanation of methodology
Your base class could be better described as a interface since your enforcing that each class implement a common property and not making common calculations or sweeping generalizations that could group schools, students, and books together.
Pursuing an event driven solution there are a few things you can do such as using BindingList<T> which is basically List<T> on steroids.
Unfortunatly, you'll need to explode your pretty little { get; set; } properties into full fields, but the best way is for each modification of a property to trigger an event. Each subsequent object that is affected by the modification is subscribed to your modified objects Modified event.
public interface IChangeAware
{
event EventHandler<EventArgs> OnChange;
DateTime ModifiedTime { get; set; }
}
public class Student : IChangeAware
{
public event EventHandler<EventArgs> OnChange;
public DateTime ModifiedTime { get; set; }
public string Name { get; set; }
public School School
{
get { return School; }
set
{
School = value;
if (this.OnChange != null)
this.OnChange(this, new EventArgs());
}
}
public Student()
{
if (School != null)
School.OnChange += MySchoolOnChange;
}
void MySchoolOnChange(object sender, EventArgs e)
{
ModifiedTime = DateTime.Now;
}
}
public class School : IChangeAware
{
public event EventHandler<EventArgs> OnChange;
public DateTime ModifiedTime { get; set; }
public string SchoolName { get; set; }
public BindingList<Book> Books { get; set; }
public School()
{
Books = new BindingList<Book>();
Books.ListChanged += BooksListChanged;
}
void BooksListChanged(object sender, ListChangedEventArgs e)
{
ModifiedTime = DateTime.Now;
OnChange(this, new EventArgs());
}
}
public class Book
{
public string BookName { get; set; }
}