c# on nested property change tracking - c#

I have a generic class with a single argument that represents an Element of a third party DLL for the purpose of serialization of objects of T kind. What I would like to do is add a 'Dirty' map to my class and lazily trigger it whenever one of my Element's nested properties are changed.
Is it possible to when the property is accessed catch the request and identify what property is changing? That if a SET is being performed I can log that sub-property P is now dirty and needs to be saved? Or at least a single bit that indicates that SOMETHING has changed?
public class ResourceSerializer<T>
where T : Base, new()
{
T element;
Dictionary<String,Boolean> dirtyMap;
public T Element { get { return this.getElement(); } }
public Boolean IsDirty { get; private set; }
public ResourceSerializer()
{
dirtyMap = new Dictionary<string,bool>();
element = new T();
// code to reflect back upon T's Properties and build out the dirtyMap.
// I already can do this I just omitted it.
// in my Person example there would be keys: 'FirstName', 'LastName', 'Age', 'Gender', 'PrimaryAddress'
}
// how can I call this programmatically?
void flagDirty(String property)
{
dirtyMap[property] = true;
this.IsDirty = true;
}
T getElement()
{
// In case I need to do a thing before returning the element.
// Not relevant to the question at hand.
return this.element;
}
}
a somewhat advanced example of 'Base'. You can see how I need to recurse my actions as not everything is a primitive. I have a manager level class that logs all of these ResourceSerializer objects.
public class Base
{
public Base()
{
}
}
public enum gender
{
Male,
Female,
Other,
Unspecified,
}
public class Address : Base
{
public String Street { get; set; }
public String State { get; set; }
public String Zip { get; set; }
public Address() : base()
{
}
}
public class Person : Base
{
public String FirstName { get; set; }
public String LastName { get; set; }
public Int16 Age { get; set; }
public gender Gender { get; set; }
public Address PrimaryAddress { get; set; }
public Person() : base()
{
}
}
public class Patient : Person
{
public Person PrimaryContact { get; set; }
public Patient() : base()
{
}
}
and a small class i would turn into a test method later..
public class DoThing
{
public DoThing()
{
ResourceSerializer<Person> person = new ResourceSerializer<Person>();
person.Element.Age = 13; // catch this and mark 'Age' as dirty.
}
}

Without a custom setter no, there's nothing to do that.
The usual pattern for what you're trying to do is implement the INotifyPropertyChanged interface, that interface is precisely created for classes (or structs) which need to track and inform about changes on their properties.
If you're lazy as me, I would create an analyzer which at the beginning of my app scans all my classes which are tagged with an attribute and with all properties created as virtual, then using codedom I would create a new class which would inherit from the found class and it implements the INotifyPropertyChanged, then you can have a generic Factory which returns instances of these new classes when the type of the generic call is of a known registered type.
I've used this before for classes which I wanted to have remote properties, just tagged the class and my scan system rewrote the getter/setter to do the remote calls transparently, the concept at the end is the same.
It's a lot of work at the begining, but if you have a ton of classes it will be a lot less of code to write than implementing INotifyPropertyChanged on all your classes.

Related

Problem in class design with multiple base model

I have a base class for all the ENTITIES of my project which is inheriting from below model :
public class BaseModel
{
public int Id { get; set; }
public int CreatedDate { get; set; }
public override string ToString();
}
Now I have 1 another functionality which is common for so many modules and I want to keep BaseModel for that functionality and want it to be inherited from it.
Public class BaseNotice
{
// Common info related to notice which is use to send notice to employees in different scenarios
}
Now our every model is suppose to inherit from BaseModel so inheriting from BaseNotice will be multiple inheritance.
Now I cannot like below :
Public class BaseNotice : BaseModel
{
// Common info related to notice which is use to send notice to employees in different scenarios
}
Because I would like to control functionality related to Notice from BaseNotice model and for notice I would like to keep BaseNotice as base model.
But I am not getting how to avoid multiple inheritance here and so what would be the proper way to design this?
There is No need to Multiple Inheritance. you can do that in this way:
public class BaseModel
{
public int Id { get; set; }
public int CreatedDate { get; set; }
public override string ToString();
}
public interface IBaseNotice
{
// Base Notices Contracts should be placed here
}
Public class BaseNotice: IBaseNotice
{
// Common info related to notice which is use to send notice to employees in different scenarios
}
public class ModelX:BaseModel
{
public IBaseNotice Notice { get ; set; }
public ModelX(IBaseNotice baseNotice)
{
Notice = baseNotice;
}
}
Or you can use Second Generation of your BaseModel:
public class BaseModeNoticable:BaseModel
{
public IBaseNotice Notice { get ; set; }
public BaseModeNoticable(IBaseNotice baseNotice)
{
Notice = baseNotice;
}
}

Overriding abstract list<a> property with list<A>

I'm writing a piece of code to make certain reports. There are 4 types of reports which the user can request. Each type report is based on the base class 'report'. Each derived class has a List. The class 'A' is derived from base class 'a'.
Is it possible to add an abstract List to the 'report' class and let it be overridden by a List in the derived report classes? Something like this?
public abstract class Report
{
public abstract List<a> Coils { get; set; }
}
public class ProductionExitCoilReport : Report
{
public override List<A> Coils { get; set; }
}
public class a
{
public string SomeProperty { get; set; }
}
public class A: a
{
public string SomeOtherProperty { get; set; }
}
I'm kind of new to C# so if I'm asking something really basic or I have a big flaw in my thinking, please do point it out. But please don't just answer with yes or no.
Based on your description of the usage, there is no need to override the List/collection in your new class. Since A inherits from a, you can store objects of type A in "Coils". (due to polymorphism). Then if, at some later time, you want to access "SomeOtherProperty" of the objects of type A, you could use a cast.
public abstract class Report
{
public List<a> Coils { get; set; }
}
public class ProductionExitCoilReport : Report
{
}
public class a
{
public string SomeProperty { get; set; }
}
public class A : a
{
public string SomeOtherProperty { get; set; }
}
public void SomeMethod()
{
//to store the coil
ProductionExitCoilReport myReport = new ProductionExitCoilReport();
myReport.Coils.Add(new A());
//to retreive SomeOtherProperty from the first element in the list
string retrievedProperty = ((A)myReport.Coils[0]).SomeOtherProperty;
}
Your properties are readable and writable.
Derived types must always be compatible with the base type.
Every Report has Coils property that returns a read/write collections of items of type a. Thus you can always write report.Coils.Add(new a()).
ProductionExitCoilReport inherits from Report, so it would have been possible to run the same code - to add a (not A) to the collection returned by Coils: ((Report)productionReport).Coils.Add(new a()).
This contradicts what you want to accomplish.
Please read about covariance and contravariance:

C# class overwrite possibility

I am having a question, and probably it can not be done this way but maybe there is some other way i do not know, so I have a class that looks like this:
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int Id { get; set; }
[DataMember(Name = "value")]
public int Value { get; set; }
}
Now this class is a attribute value of different class:
[DataContract]
public class Location
{
[DataMember(Name="parent")]
public Parent Parent { get; set; }
}
But there is a catch, I need separate classes bout same type for example:
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int Id { get; set; }
}
[DataContract]
public class Parent
{
[DataMember(Name = "value")]
public int Value { get; set; }
}
Depending if Value is null or not (and I need this to be separate object cause as you see I want to map this). Is it possible to overwrite class so one class can have one or other attribute only?
You could solve it with inheritance, but IMHO it gets overdesigned.
Personally, I would all put into the Parent class. Make the properties nullable, than it's done. If you want to have some reliability that at least one property is set, you may want to make the setters private (given that you don't need to change them after creating the parent) and have factory methods to create parents with an Id or a Value.
Parent with encapsulation (if required):
[DataContract]
public class Parent
{
private Parent() {}
[DataMember(Name="id")]
public int? Id { get; private set; }
[DataMember(Name = "value")]
public int? Value { get; private set; }
public static Parent CreateWithId(int id)
{
return new Parent { Id = id };
}
public static Parent CreateWithValue(int value)
{
return new Parent { Value = value };
}
}
You can further add a ParentType property which returns an enum value which is either ParentType.ValueParent or ParentType.IdParent. Again, this is only useful when required, e.g. because it simplifies handling of parents, when there is a chance to get more different types or when you may want to support Id Parents with a null value as Id or the same with the Value.
Completely different solution is to store both Id and Value in the same property, since both are integers. Have another way to distinguish wether it is a Id or a Value.
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int Data { get; private set; }
[DataMember(Name="id")]
public ParentType ParentType { get; private set; }
public static Parent CreateWithId(int id)
{
return new Parent { Data = id, ParentType = ParentType.Id };
}
public static Parent CreateWithValue(int value)
{
return new Parent { Data = value, ParentType = ParentType.Value };
}
}
You're trying to represent DIFFERENT data by creating two different classes which are named the same. This is an error. Initially I wanted to suggest using interfaces or inheritance, but that makes no sense, as both Parent classes you wrote contain different things and there's no overlap.
If this case is directed purely because you need to map those properties to some data contract, then why not have a Parent class with both properties and just make those properties Nullable?
Something along the lines:
[DataContract]
public class Parent
{
[DataMember(Name="id")]
public int? Id { get; set; }
[DataMember(Name = "value")]
public int? Value { get; set; }
}
1 As said HimBromBree, you can put Parent classes in different namespaces.
WCF also allows you to provide different names for Serialization of classes through [DataContract] attribute :
[DataContract(Name="ParentA")]
public class Parent {
[DataMember(Name="id")]
public int Id { get; set; }
}
2 If your goal is to have Parent class to hold different values (Value or Id) depending on circumstances, you can also create two derived classes of Parent.
Let's call those classes ParentA and ParentB
Then on Parent, you should make a declaration for polymorphic serialization :
[DataContract]
[KnownType(typeof(ParentA))]
[KnownType(typeof(ParentB))]
public class Parent {}
[DataContract(Name="ParentA")]
public class ParentA : Parent {
[DataMember(Name="id")]
public int Id { get; set; }
}

Design Pattern for derived classes also having a derived child property

I'm looking for a class structure or design pattern to implement a base class that has a list of "base items", where several derived classes have the same list but that list is of derived "base items".
Here's a vastly stripped down example (ignore the accessibility of properties, they wouldn't actually all have public setters and default constructors):
public class BaseTransaction {
public List<BaseTransactionItem> Items { get; set; }
public void AddItem(string description, int quantity, decimal price)
{
// Add a new BaseTransactionItem to Items
}
}
public class BaseTransactionItem {
public string Description { get; set; }
public int Quantity { get; set; }
public decimal Price { get; set; }
}
public class OrderTransaction : BaseTransaction {
public List<OrderTransactionItem> Items { get; set; }
public int Deposit { get; set; }
public void SetDeposit(int depositAmount)
{
// Do some stuff to set the deposit.
}
}
public class OrderTransactionItem : BaseTransactionItem
{
public int QuantityFulfilled { get; set; }
}
public class RetailTransaction : BaseTransaction {
public List<RetailTransactionItem> Items { get; set; }
public List<Tender> Tenders { get; set; }
public void AddTender(Tender tender)
{
// Add a tender to the RetailTransaction
}
public decimal TotalTax
{
get { return Items.Sum(i => i.Tax); }
}
}
public class RetailTransactionItem : BaseTransactionItem
{
public decimal Tax { get; set; }
}
The way I need to work with these classes is that you start with a BaseTransaction and add some items to it, and then it can become either an OrderTransaction or a RetailTransaction. These both share most of their logic and properties with a BaseTransaction but have specific extra fields and methods, as well as the List<BaseTransactionItem> becoming a List<OrderTransactionItem> or a List<RetailTransactionItem> respectively.
Further more, after a BaseTransaction is "promoted" to a RetailTransaction, it may be "demoted" back to a BaseTransaction and then "promoted" to an OrderTransaction (but never from a RetailTransaction to an OrderTransaction in this case).
I've tried several approaches to this, with generics, the Decorator pattern (which doesn't seem appropriate), TypeConverters, and yet nothing seems to fit. The only possible solution I've thought of that works is having the RetailTransaction class have a constructor that takes a BaseTransaction and copying over all the properties and converting the list using .Cast<RetailTransactionItem> but this will make maintaining the derived classes pretty difficult.
If it wasn't for the list type needing to change this would be a simple case of using inheritance. I'm completely open to alternative approaches such as those favouring composition over inheritance but since the RetailTransaction and OrderTransaction classes truely are more specific versions of BaseTransaction, inheritance seems to fit - at least in my mind.

Group Properties within partial class

I have 5 Properties within my class that are all very similar; I want to group them. The class they are contained in used to look like this:
class Car
{
public string PropA { get; set; }
public string PropB { get; set; }
public string PropC { get; set; }
public Car() { }
}
So with Intellisense, I would be presented with:
Car car = new Car();
car.PropA
.PropB
.PropC
..I would be presented with the 3 properties. What I want is for it to be contained within it's own little group, so I would have to do:
car.Props.PropA = "example";
I created a partial class to hide them in, but I am not sure if this is the correct way to do it:
class Car
{
public Props { get; set; }
public Car() { }
}
partial class Props
{
public string PropA { get; set; }
public string PropB { get; set; }
public string PropC { get; set; }
}
Is there a better way to go about this? I ask because I am creating a class library and usability is very important.
The partial keyword is used to split a class's implementation among multiple files. Knowing that, it doesn't help (or hurt) in this situation.
Without knowing more about your design, your solution seems reasonable. Just get rid of the partial keyword, it's not appropriate here.
Agreed with what Patrick said. I had a question about your public setters though, and this is something I've been curious about how to handle myself.
if you're hoping for other people to use thing class (and assuming this wasn't just a mocked up example) are you sure you want people to just be able to willy nilly be able to set properties in your classes without going through a method/function that validates and/or handles the setting of the property?
this can be done like:
public class Props
{
public string PropA { get; private set; }
public string PropB { get; private set; }
public string PropC { get; private set; }
}
public Props() { }
public SetProps(string propA, string propB, string propC)
{
this.PropA = propA;
this.PropB = propB;
this.PropC = propC;
}
Now obviously doing something like this would depend on the nature of the requirements around the props (and this is an extremely simple example - all props have to be set at the same time). But with public setters a user of the class would not necessarily know the nature of the requirements, and the public setters could potentially allow them a way around how it was intended the class be used.

Categories