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; }
}
Related
I'm doing and WPF application and I have a ViewModel that I use in several Views and in DataGrids.
Now I have another View that requires an extended or decorated version of that ViewModel. So I decided to go for inheritance in this way:
public class StandardViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class ExtendedViewModel : StandardViewModel
{
public string Email { get; set; }
}
However, I want to decorate and existing instance of the StandardViewModel. Specifically the selected object in the DataGrid so it can be passed into the other View.
The new View needs access to the properties of both classes (the Email and the FirtsName and LastName)
So I'm thinking of ways to creating a constructor for my ExtendedViewModel.
My idea is to copy the base instance directly.
Is this correct?
And efficient?
Is there any other way of doing it?
public class ExtendedViewModel : StandardViewModel
{
public string Email { get; set; }
public ExtendedViewModel(StandardViewModel base)
{
this = base
}
}
Edit
I'm doing this for not only one but several classes. And they do not have only two properties so I'm trying to avoid copying the values one by one.
Finally I'll avoid using inheritance and I'll create a new class, expose the base class and subscribe to INotifyPropertyChanged as described here and here.
This way I'll be able to have properties that depend on the Base ViewModel updated as done with FullName below.
The resulting ViewModel will look like:
public class ExtendedViewModel
{
public StandardViewModel Base { get; set; }
public string Email { get; set; }
public string FullName {
get => Base.FirstName + Base.LastName;
}
public ExtendedViewModel(StandardViewModel base)
{
Base = base
Base.PropertyChanged += BaseChanged
}
private void BaseChanged(object sender, PropertyChangedEventArgs e)
{
// Here check if FirstName or LastName changed and
RaisePropertyChanged("FullName");
}
}
In the view I will bind directly to Email or to Base.FirstName.
In oversimplified terms a decorator owns an instance of the class it decorates and delegates functionality existing in the owned class to that class, while adding new functionality uncoupled from the owned class instance.
public class StandardViewModel
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
}
public class ExtendedViewModel : StandardViewModel
{
private StandardViewModel _standard;
public ExtendedViewModel (StandardViewModel standard)
{
if (standard.GetType() != typeof(StandardViewModel )) {
throw new ArgumentException ("Expected a non derived standard view model", nameof(standard));
}
_standard = standard;
}
public string Email { get; set; }
public override string FirstName {
get => _standard.Firstname;
set => _standard.Firstname = value;
}
public override string LastName {
get => _standard.LastName;
set => _standard.LastName = value;
}
}
For my example classes to be stored are lets say:
class Race
{
public string Name { get; set; }
public DateTime Date { get; set; }
public List<Competitor> Competitors = new List<Competitor>();
}
class Competitor
{
public string Name { get; set; }
public List<Stats> SomeData = new List<Stats>():
}
class Stats
{
//Other Properties Etc
}
They are to be stored in :
class Events : Dictionary<string, List<Race>>
{
public Events()
: base()
{
}
}
And I fill the Dictionary with another class :
class GenerateEventsData
{
public Events newEvents = new Events();
public GenerateEventsData()
{
fillEvents();
}
private void fillEvents()
{
//Method to fill events.
}
}
I feel as though I'm getting to a stage where lists of classes are being stacked up and my structure is not correct.
I plan to eventually serialize the data to disk and re-use at a later date but that's beyond the bounds of this question. However if the classes aren't well structured i think i may have issues.
Thanks in advance.
you could use a generic container:
public class ListDictionary<T> : Dictionary<string,List<T>>
{
public ListDictionary():base(){}
public void AddItem(string key, T value)
{
if(ContainsKey(key))
this[key].Add(value);
else
Add(key,new List<T>{value});
}
//similar for remove and get
}
Also have a look at the repository pattern.
Many tables in my database have common fields which I call 'audit' fields. They fields like - UserUpdateId, UserCreateId, DateUpdated, DateCreated, DateDeleted, RowGUID, as well as a common "Comments" table etc. In the database they are used to track who did what when. Additionally via the asp.net MVC 4 views they display these attributes to the user using common display templates (popup, mouseover etc.).
Currently, I put these properties into a [Serializable()] CommonAttributesBase class. Which I then initialize in all the models that should inherit those properties. Admittedly this is a little clunky and inefficient as my CommonAttribute class makes calls to the repository and the initialization seems like more code than necessary.
I would appreciate suggestions on how to implement this in the best way.
[Serializable()]
public class CommonAttributesBase
{
#region Notes
public Boolean AllowNotes { get; set; }
[UIHint("NoteIcon")]
public NoteCollection NoteCollection
{
get
{
if (!AllowNotes) return null;
INoteRepository noteRepository = new NoteRepository();
var notes = noteRepository.FindAssociatedNotes(RowGUID);
return new NoteCollection { ParentGuid = RowGUID, Notes = notes, AuditString = AuditTrail };
}
}
#region Audit Trail related
public void SetAuditProperties(Guid rowGuid, Guid insertUserGuid, Guid updateUserGuid, Guid? deleteUserGuid, DateTime updateDate, DateTime insertDate, DateTime? deleteDate)
{
RowGUID = rowGuid;
InsertUserGUID = insertUserGuid;
UpdateUserGUID = updateUserGuid;
DeleteUserGUID = deleteUserGuid;
UpdateDate = updateDate;
InsertDate = insertDate;
DeleteDate = deleteDate;
}
[UIHint("AuditTrail")]
public string AuditTrail
{
get
{
...code to produce readable user audit strings
return auditTrail;
}
}
...additional methods
}
In another class
public partial class SomeModel
{
private CommonAttributesBase _common;
public CommonAttributesBase Common
{
get
{
if (_common == null)
{
_common = new CommonAttributesBase { AllowNotes = true, AllowAttachments = true, RowGUID = RowGUID };
_common.SetAuditProperties(RowGUID, InsertUserGUID, UpdateUserGUID, DeleteUserGUID, UpdateDate, InsertDate, DeleteDate);
}
return _common;
}
set
{
_common = value;
}
}
...rest of model
}
For me, I prefer to use different interfaces for each type (audit or note), and use decorator to retrieve those related data, instead of embedding those in the common class:
public class Note
{
//Node properties
}
public class AuditTrail
{
//Audit trail properties
}
public interface IAuditable
{
AuditTrail AuditTrail { get; set; }
}
public interface IHaveNotes
{
IList<Note> Notes { get; set; }
}
public class SomeModel : IAuditable, IHaveNotes
{
public IList<Note> Notes { get; set; }
public AuditTrail AuditTrail { get; set; }
public SomeModel()
{
Notes = new List<Note>();
}
}
public class AuditRepository : IRepository<T> where T : IAuditable
{
private IRepository<T> _decorated;
public AuditRepository(IRepository<T> decorated)
{
_decorated = decorated;
}
public T Find(int id)
{
var model = _decorated.Find(id);
model.Audit = //Access database to get audit
return model;
}
//Other methods
}
public class NoteRepository : IRepository<T> where T : IHaveNotes
{
private IRepository<T> _decorated;
public NoteRepository(IRepository<T> decorated)
{
_decorated = decorated;
}
public T Find(int id)
{
var model = _decorated.Find(id);
model.Notes = //Access database to get notes
return model;
}
//Other methods
}
Advantages is that the client will be able to choose to load audit/note or not, the logic of audit and note are also separated from the main entity repository.
What you're doing is basically composition. As others have stated, there's many ways to accomplish what you're looking for, some better than others, but each method depends on the needs of your application, of which only you can speak to.
Composition
Composition involves objects having other objects. For example, if you were going to model a car, you might have something like:
public class Car
{
public Engine Engine { get; set; }
}
public class Engine
{
public int Horsepower { get; set; }
}
The benefit to this approach is that your Car ends up with a Horsepower property via Engine, but there's no inheritance chain. In other words, your Car class is free to inherit from another class while not effecting this property or similar properties. The problems with this approach is that you have to involve a separate object, which in normally is not too troubling, but when combined when tied back to a database, you're now talking about having a foreign key to another table, which you'll have to join in order to get all the class' properties.
Entity Framework allows you to somewhat mitigate this effect by using what it calls "complex types".
[ComplexType]
public class Engine
{
...
}
The properties of complex types are mapped onto the table for the main class, so no joins are involved. However, because of this, complex types have certain limitations. Namely, they cannot contain navigation properties -- only scalar properties. Also, you need to take care to instantiate the complex type or you can run into problems. For example, any nulled navigation property is not validated by the modelbinder, but if you have a property on your complex type that is required (which results in a property on your main class' table that is non-nullable), and you save your main class while the complex type property is null, you'll get an insertion error from the database. To be safe you should always do something like:
public class Car
{
public Car()
{
Engine = new Engine();
}
}
Or,
public class Car
{
private Engine engine;
public Engine Engine
{
get
{
if (engine == null)
{
engine = new Engine();
}
return engine;
}
set { engine = value; }
}
}
Inheritance
Inheritance involves deriving your class from a base class and thereby getting all the members of that base class. It's the most straight-forward approach, but also the most limiting. This is mostly because all of the .NET family of languages only allow single inheritance. For example:
public class Flyer
{
public int WingSpan { get; set; }
}
public class Walker
{
public int NumberOfLegs { get; set; }
}
public class Swimmer
{
public bool HasFlippers { get; set; }
}
public class Duck : ????
{
...
}
That's a bit contrived, but the point is that Duck is all of a Flyer, Walker and Swimmer, but it can only inherit from one of these. You have to be careful when using inheritance in languages that only allow single inheritance to make sure that what you inherit from is the most complete base class possible, because you won't be able to easily diverge from this.
Interfaces
Using interfaces is somewhat similar to inheritance, but with the added benefit that you can implement multiple interfaces. However, the downside is that the actual implementation is not inherited. In the previous example with the duck, you could do:
public class Duck : IFlyer, IWalker, ISwimmer
However, you would be responsible for implementing all the members of those interfaces on your Duck class manually, whereas with inheritance they just come through the base class.
A neat trick with interfaces and .NET's ability to extend things is that you can do interface extensions. These won't help you with things like properties, but you can move off the implementation of some of the class' methods. For example:
public static class IFlyerExtensions
{
public static string Fly(this IFlyer flyer)
{
return "I'm flying";
}
}
Then,
var duck = new Duck();
Console.WriteLine(duck.Fly());
Just by implementing IFlyer, Duck gets a Fly method, because IFlyer was extended with that method. Again, this doesn't solve every problem, but it does allow interfaces to be somewhat more flexible.
There's a couple different ways you could do something like this. I personally haven't worked with EF so I can't speak in regards to how it will work.
Option One: Interfaces
public interface IAuditable
{
Guid RowGUID { get; }
Guid InsertUserGUID { get; }
Guid UpdateUserGUID { get; }
Guid DeleteUserGUID { get; }
DateTime UpdateDate { get; }
DateTime InsertDate { get; }
DateTime DeleteDate { get; }
}
Of course you can change it to get and set if your use cases need that.
Option Two: Super/base classes
public abstract class AuditableBase
{
// Feel free to modify the access modifiers of the get/set and even the properties themselves to fit your use case.
public Guid RowGUID { get; set;}
public Guid InsertUserGUID { get; set;}
public Guid UpdateUserGUID { get; set;}
public Guid DeleteUserGUID { get; set;}
public DateTime UpdateDate { get; set;}
public DateTime InsertDate { get; set;}
public DateTime DeleteDate { get; set;}
// Don't forget a protected constructor if you need it!
}
public class SomeModel : AuditableBase { } // This has all of the properties and methods of the AuditableBase class.
The problem with this is that if you cannot inherit multiple base classes, but you can implement multiple interfaces.
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();
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.