Automatic update existing Class properties from an instance of the same class - c#

Well recently i came up with an idea (that i really don't know whether it would exist or even work) of automatic updating class's properties using an modified instance of it. And to make my idea a little bit more clear, i will explain it in the code below.
//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;
//Here is the same employee data collected from the database a year after...
Employee carl_one_year_later = new Employee();
carl_one_year_later.Age = 21;
carl_one_year_later.Salary = 10000;
//Here comes the idea... I wanna dynamically merge the new collected data to the current main instance of the employee, without missing out the unupdated data ex : his name
employee1 = employee2; //using this seems to overwrite the Name Field with null...
Someone might say you can simply achieve this by doing this:
carl.Age = carl_one_year_later.Age;
carl.Salary = carl_one_year_later.Salary;
However, i want a dynamic way to just do this in 1 line of code and let C# handle the property set for me, also it may come in handy if we have a massive class that we don't want to set it's properties every time it is updated one by one.
NB: I hope i succeed in providing a clear image of my idea, and if you find any problem understanding what exactly do i need, just let me know.

using System;
using System.Reflection;
public class Test
{
public class Employee
{
public String Name{get;set;}
public int Age{get;set;}
public int Salary{get;set;}
}
public static void Main()
{
Employee e1 = new Employee{Name="Old", Age=20, Salary=1000};
Employee e2 = new Employee{Age=30, Salary=5000};
Copy(e2, e1);
Console.WriteLine(e1.Name+" "+ e1.Age+" "+e1.Salary );
}
public static void Copy<T>(T from, T to)
{
Type t = typeof (T);
PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props) {
if (!p.CanRead || !p.CanWrite) continue;
object val = p.GetGetMethod().Invoke(from, null);
object defaultVal = p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null;
if (null != defaultVal && !val.Equals(defaultVal)) {
p.GetSetMethod().Invoke(to, new[] {val});
}
}
}
}

You can make a CopyTo extension method, like so:
public static class ObjectExtensions
{
public static void CopyTo<T>(this T fromObj, T toObj)
{
foreach(var p in typeof(T).GetProperties())
{
p.SetValue(toObj, p.GetValue(fromObj, null), null);
}
}
}
And call it like:
carl_one_year_later.CopyTo(carl);
Although, to be honest, there's a few more checks that should be made, and you'd be better off using something like AutoMapper instead.

Checkout ICloneable OR MemberwiseClone (unless you need to do a deep copy. Then check out a object mapper like Automapper, ValueInjecter or write your own custom object serialization hydrater)
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
The MemberwiseClone method creates a shallow copy by creating a new object, and then copying the nonstatic fields of the current object to the new object.
http://msdn.microsoft.com/en-us/library/system.icloneable.aspx
Alternatives to AutoMapper

public static class ObjectExtensions
{
public static void CopyTo<T>(this T fromObj, T toObj)
{
foreach (var p in typeof(T).GetProperties())
{
if(p.GetValue(fromObj) == null)
{
continue;
}
p.SetValue(toObj, p.GetValue(fromObj, null), null);
}
}
}
Same as the above answer but just added "if" in "foreach" to skip the null values

The idea itself seems odd to me..
I, myself, would just rather do :
//The first (Main) instance of the class
Employee carl = new Employee();
carl.Name = "Carl";
carl.Age = 20;
carl.Salary = 7000;
//Here we get Carl from the database
Employee carl = GetFromDatabase("Carl") //Illustration
carl.Age = 21;
carl.Salary = 10000;
Your code is like saying nowadays Carl and next year Carl is a completely different person, and coincidentally having all those same attributes.
Although if it really needs to be done, I do tend to prefer Automapper..

Related

Replace (and backup) Method dynamically in C#

I need to change a specific property dynamically and have been using this snipplet:
var _oldMethod = typeof(TypeName).GetProperty("OldProperty", BindingFlags.Public | BindingFlags.Static).GetMethod;
var _newMethod = typeof(OwnTypeName).GetProperty("NewProperty", BindingFlags.Public | BindingFlags.Static).GetMethod;
ReplaceMethod(_oldMethod, _newMethod);
...
private static unsafe void ReplaceMethod(MethodInfo _oldMethod, MethodInfo _newMethod)
{
var _oldMethodAddress = new IntPtr((int*)_oldMethod.MethodHandle.Value.ToPointer() + 2);
var _destination = (uint*)_oldMethodAddress.ToPointer();
*destination = (uint)_newMethod.MethodHandle.GetFunctionPointer().ToInt32();
}
Unfortunately this required some decompiling with recreating the original property. What I am looking for now is a a possibility to duplicate and kind of backup the original method and dynamically replace the old method with the new one or restore the original one.
Has anyone an idea how to implement this?
Edit:
I may should have clarified my situation further:
public static class ClassName
{
public static bool Property
{
get
{
// Conditions
}
}
}
I can't access ClassName and need to force Property to false in specific situations and need to replace it to the original return value in other situations. I have been using the ReplaceMethod above mentioned but don't want to decompile and rebuild Property from scratch (instead some kind of backup of the original Property)
First of all, you are handling properties instead of methods.
One easy approach to do this is to replace your properties type by Func<> and this will keep what you're wanting to do easier.
private static void Main(string[] args)
{
var a = new A();
a.Property = Method1;
Console.WriteLine(a.Property.Invoke());
a.Property = Method2;
Console.WriteLine(a.Property.Invoke());
Func<string> oldMethod = a.Property;
Console.WriteLine(oldMethod.Invoke());
Console.ReadLine();
}
public class A
{
public Func<string> Property { get; set; }
}
private static string Method1()
{
return "Method1";
}
private static string Method2()
{
return "Method2";
}
You can change the method as many times as you want and also keep the old one in one variable.

Best way to create instance of child object from parent object

I'm creating a child object from a parent object. So the scenario is that I have an object and a child object which adds a distance property for scenarios where I want to search. I've chosen to use inheritance as my UI works equivalently with either a search object or a list of objects not the result of a location search. So in this case inheritance seems a sensible choice.
As present I need to generate a new object MyObjectSearch from an instance of MyObject. At present I'm doing this in the constructor manually by setting properties one by one. I could use reflection but this would be slow. Is there a better way of achieving this kind of object enhancement?
Hopefully my code below illustrates the scenario.
public class MyObject {
// Some properties and a location.
}
public class MyObjectSearch : MyObject {
public double Distance { get; set; }
public MyObjectSearch(MyObject obj) {
base.Prop1 = obj.Prop1;
base.Prop2 = obj.Prop2;
}
}
And my search function:
public List<MyObjectSearch> DoSearch(Location loc) {
var myObjectSearchList = new List<MyObjectSearch>();
foreach (var object in myObjectList) {
var distance = getDistance();
var myObjectSearch = new MyObjectSearch(object);
myObjectSearch.Distance = distance;
myObjectSearchList.add(myObjectSearch);
}
return myObjectSearchList;
}
The base class needs to define a copy constructor:
public class MyObject
{
protected MyObject(MyObject other)
{
this.Prop1=other.Prop1;
this.Prop2=other.Prop2;
}
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class MyObjectSearch : MyObject
{
public double Distance { get; set; }
public MyObjectSearch(MyObject obj)
: base(obj)
{
this.Distance=0;
}
public MyObjectSearch(MyObjectSearch other)
: base(other)
{
this.Distance=other.Distance;
}
}
This way the setting of properties is handled for all derived classes by the base class.
You can use reflection to copy properties.
public class ChildClass : ParentClass
{
public ChildClass(ParentClass ch)
{
foreach (var prop in ch.GetType().GetProperties())
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(ch, null), null);
}
}
}
There is no easy way to do this, unfortunately. As you said, you would either have to use reflection, or create a "Clone" method that would generate a new child object using a parent object as input, like so:
public class MyObjectSearch : MyObject {
// Other code
public static MyObjectSearch CloneFromMyObject(MyObject obj)
{
var newObj = new MyObjectSearch();
// Copy properties here
obj.Prop1 = newObj.Prop1;
return newObj;
}
}
No matter what, you're either going to end up writing reflection code (which is slow), or writing each property out by hand. It all depends on whether or not you want maintainability (reflection) or speed (manual property copy).
A generic solution would be to serialize it to json and back. In the json-string is no information about the class name from which it was serialized.
Most people do this in javascript.
As you see it works well for pocco objects but i don't guarantee that it works in every complex case. But it does event for not-inherited classes when the properties are matched.
using Newtonsoft.Json;
namespace CastParentToChild
{
public class Program
{
public static void Main(string[] args)
{
var p = new parent();
p.a=111;
var s = JsonConvert.SerializeObject(p);
var c1 = JsonConvert.DeserializeObject<child1>(s);
var c2 = JsonConvert.DeserializeObject<child2>(s);
var foreigner = JsonConvert.DeserializeObject<NoFamily>(s);
bool allWorks = p.a == c1.a && p.a == c2.a && p.a == foreigner.a;
//Your code goes here
Console.WriteLine("Is convertable: "+allWorks + c2.b);
}
}
public class parent{
public int a;
}
public class child1 : parent{
public int b=12345;
}
public class child2 : child1{
}
public class NoFamily{
public int a;
public int b = 99999;
}
// Is not Deserializeable because
// Error 'NoFamily2' does not contain a definition for 'a' and no extension method 'a' accepting a first argument of type 'NoFamily2' could be found (are you missing a using directive or an assembly reference?)
public class NoFamily2{
public int b;
}
}
If a shallow copy is enough, you can use the MemberwiseClone method.
Example:
MyObject shallowClone = (MyObject)original.MemberwiseClone();
If you need a deep copy, you can serialize/deserialize like this: https://stackoverflow.com/a/78612/1105687
An example (assuming you write an extension method as suggested in that answer, and you call it DeepClone)
MyObject deepClone = original.DeepClone();
I first came accros this question when I was looking for doing this.
If you are able to work with C# 9 and record-classes. You only have to create a new constructor in the sub-class taking in a base class object and hand it over to the subclass:
public record MyObject {
...
}
public record MyObjectSearch :MyObject
{
public MyObjectSearch(MyObject parent) : base(parent) { }
...
}
Then you can create the child object like this:
MyObject parent = new();
MyObjectSearch m = new MyObjectSearch(parentObj) { Distance = 1.1};
Credits to https://stackoverflow.com/a/64573044/2582968
Seems natural for the base object to have constructor with parameters for its properties:
public class MyObject
{
public MyObject(prop1, prop2, ...)
{
this.Prop1 = prop1;
this.Prop2 = prop2;
}
}
So then, in your descendant object you can have:
public MyObjectSearch(MyObject obj)
:base(obj.Prop1, obj.Prop2)
This reduces duplication related to assignments. You could use reflection to automatically copy all properties, but this way seems more readable.
Note also, that if your classes have so much properties that you're thinking about automatizing of copying of the properties, then they are likely to violate the Single Responsibility Principle, and you should rather consider changing your design.
There are libraries to handle this; but if you just want a quick implementation in a few places, I would definitely go for a "copy constructor" as previously suggested.
One interesting point not mentioned is that if an object is a subclass, then it can access the child's private variables from the within the parent!
So, on the parent add a CloneIntoChild method. In my example:
Order is the parent class
OrderSnapshot is the child class
_bestPrice is a non-readonly private member on Order. But Order can set it for OrderSnapshot.
Example:
public OrderSnapshot CloneIntoChild()
{
OrderSnapshot sn = new OrderSnapshot()
{
_bestPrice = this._bestPrice,
_closed = this._closed,
_opened = this._opened,
_state = this._state
};
return sn;
}
NOTE: Readonly member variables MUST be set in the constructor, so you will have to use the child constructor to set these...
Although I don't like "up-sizing" generally, I use this approach a lot for analytic snapshots...

Is this the correct way of creating and using a custom attribute on a method and a class?

I've been playing around with custom attributes this evening to see if I could simplify my caching layer. I have come up with the following:
namespace AttributeCreationTest
{
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false)]
public class Cache : Attribute
{
public Cache()
{
Length = "01h:30m";
}
public string Length;
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class CacheIdentifier : Attribute
{
}
[Cache]
class Class1
{
[CacheIdentifier]
public int ID { get; set; }
}
class Class2
{
[CacheIdentifier]
public bool ID { get; set; }
}
[Cache(Length = "01h:10m")]
class Class3
{
[CacheIdentifier]
public string ID { get; set; }
}
class Program
{
static void Main(string[] args)
{
var f1 = new Class1 { ID = 2 };
var f2 = new Class2 { ID = false };
var f3 = new Class3 { ID = "someID" };
DoCache(f1);
DoCache(f2);
DoCache(f3);
}
public static void DoCache(object objectToCache)
{
var t = objectToCache.GetType();
var attr = Attribute.GetCustomAttribute(t, typeof(Cache));
if (attr == null) return;
var a = (Cache)attr;
TimeSpan span;
if (TimeSpan.TryParse(a.Length.Replace("m", "").Replace("h", ""), out span))
{
Console.WriteLine("name: {0}, {1}", t.Name, span);
ExtractCacheData(objectToCache);
return;
}
throw new Exception(string.Format("The Length value of {0} for the class {1} is invalid.", a.Length, t.Name));
}
public static void ExtractCacheData(object o)
{
var t = o.GetType();
foreach (var prop in t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (Attribute.IsDefined(prop, typeof(CacheIdentifier)))
{
Console.WriteLine(" type: {0}, value {1}", prop.PropertyType, prop.GetValue(o));
break;
}
throw new Exception(string.Format("A CacheIdentifier attribute has not been defined for {0}.", t.Name));
}
}
}
}
The "Cache" attribute will be fleshed out, but I've left it minimal whilst learning this area of C#. My idea was to allow easier caching of items, including a simplified method of specifying amount of time to cache an object.
Does this look ok? Would there be any significant performance hits from using this kind of pattern to push items to cache?
I haven't been able to find any tutorials which cover this kind of idea in any detail, so any advice would be appreciated.
Your implementation seems to be fine, but CacheAttribute object will be one per attribute declaration, not per Class1 object. In other words it doesn't matter how many objects you will create - if attribute will be assigned only once - the object of that attribute with Length property will be only one in clr.
But why don't you want to pass into DoCache method some interface, which you will define some method to retrieve a CacheIdentifier from an object? Such implementation will be more robust, exact, readable. Surely you need to implement it in each class - but I don't see lots of benefits in passing object into DoCache without specifying any of its responsibilities. For user this API is not intuitive and hard to understand.
Another point, more advanced if you will - for caching purposes I suggest to look at Aspect-Oriented Programming in general and at PostSharp in particular. This article 5 Ways That Postsharp Can SOLIDify Your Code: Caching makes a great case for implementing caching aspects. Briefly, PostSharp also uses attributes and inserts caching behavior at second step of compilation via IL weaving
EDIT: If you want nice and clean model without any distortions of non-domain elements, I suggest another AOP technique, known as dynamic interception. Most popular frameworks are LinFu and Castle Dynamic Proxy. As result, you will have your dependencies specified via constructor and IoC container will create proxies, when resolving these dependencies. But the point is that those models will know nothing about that proxies and will use them as there where simple objects. This is somewhat similar to the Decorator pattern
Your usage is fundamentally correct, but you might want to cache your results. Instead of passing instances of object you can pass types to it. Furthermore, to avoid having to use Reflection each time -- Which doesn't certainly speed up your program's execution -- You can keep the types and their relative attributes, once found, in a dictionary, and do a lookup each time that the method is called, then operate through Reflection only if the lookup fails.
Also, not obligatory, but I suggest you to follow the naming convention for attributes.
Example to keep your result cached:
static readonly Dictionary<Type, Attribute> CacheAttributes =
new Dictionary<Type,Attribute>();
Then you would modify DoCache as follows:
var t = objectToCache.GetType();
Attribute attr;
var success = CacheAttributes.TryGetValue(t, out attr);
if (!success)
{
attr = Attribute.GetCustomAttribute(t, typeof (CacheAttribute));
CacheAttributes[t] = attr;
}
if (attr == null) return;
var a = attr as CacheAttribute;
TimeSpan span;
//Continues with your code
You can apply the same concept to ExtractCacheData.

c# Quick way to undef all parameters

I have a C# winform app which is doing a lot of calculation. there is a "run" button to trigger the process. I would like to be able to "re-trigger or re-run or re-submit" the information without having to restart the program. Problem is I have a lot of variables that need to be reset. Is there a way to undef (reset) all parameters?
private Double jtime, jendtime, jebegintime, javerage, .... on and on
Create an instance of an object that stores these variables. Reference this object, and when wanting to "reset", reinstantiate your object. e.g.
public class SomeClass
{
public double jTime;
...
}
...
SomeClass sc = new SomeClass();
sc.jTime = 1;
sc = new SomeClass();
The best way would have been if you had them all in a class.
Then on reset you'd just create a new class with initialized values.
You could use Reflection; although Reflection is the less performant than the other proposed solutions, but I am not entirely sure of your solution domain and Reflection might be a good option.
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Data data = new Data();
//Gets all fields
FieldInfo[] fields = typeof(Data).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);
foreach (var field in fields)
{
//Might want to put some logic here to determin a type of the field eg: (int, double)
//etc and based on that set a value
//Resets the value of the field;
field.SetValue(data, 0);
}
Console.ReadLine();
}
public class Data
{
private Double jtime, jendtime, jebegintime, javerage = 10;
}
}
}
Yes, simply use Extract Method refactoring technique. Basically extract reset logic in a separate method and then just call it when need
private void ResetContext()
{
jtime = jendtime = jebegintime = javerage = 0;
}

How to copy data from different classes by matching field or property names

I am looking to find a way to take two objects that have identical properties and make a call to copy the property values from one object into the other. The the example below assume I have an instance of A and I want to use the data of that instance to hydrate a new instance or C (to keep things terse I used fields instead of properties in the example below)
public class A : B
{
public string prop1;
public int prop2;
}
public class B
{
public byte propX;
public float propY;
}
public class C
{
public byte propX;
public float propY;
public string prop1;
public int prop2;
}
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
//do some work
//maybe <T> generically refactor?
}
}
The merger class is just a psuedo-example, doing this through generics would be optimal but the first thing I question is whether such a capability already exists. I could imagine using reflection to do this myself but just wanted to toss it out for better ideas first.
Real world context: This is actually an MVVM related issue as I am trying to use disparate classes coming back from EF to populate a ViewModel instance.
Check out tools and libraries like AutoMapper - those would handle cases like this with ease - and much more! No need to re-invent the wheel - just use the tool! :-)
You would basically define a map between classes A and C like this:
Mapper.CreateMap<A, C>();
and then later on, you can have AutoMapper do the mapping, based on that map, from an instance of A into an instance of C, something like this:
C yourC = Mapper.Map<A, C>(instanceOfA);
AutoMapper does a default mapping based on property names (and types), but you can extend and influence it in a great many ways to include mappings from one property to another, even if the names (or types) don't match 100%. It's quite flexible and well established - definitely worth a serious look!
using System;
using System.Linq;
using System.Reflection;
public class Merger
{
public static TTarget Merge<TTarget>(object copyFrom) where TTarget : new()
{
var flags = BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic;
var targetDic = typeof(TTarget).GetFields(flags)
.ToDictionary(f => f.Name);
var ret = new TTarget();
foreach (var f in copyFrom.GetType().GetFields(flags))
{
if (targetDic.ContainsKey(f.Name))
targetDic[f.Name].SetValue(ret, f.GetValue(copyFrom));
else
throw new InvalidOperationException(string.Format(
"The field “{0}” has no corresponding field in the type “{1}”.",
f.Name, typeof(TTarget).FullName));
}
return ret;
}
}
class Program
{
static void Main(string[] args)
{
var a = new A { prop1 = "one", prop2 = 2, propX = 127, propY = 0.47f };
var c = Merger.Merge<C>(a);
Console.WriteLine(c.prop1); // prints one
Console.WriteLine(c.prop2); // prints 2
Console.WriteLine(c.propX); // prints 127
Console.WriteLine(c.propY); // prints 0.47
}
}
This isn't the best solution by far, but based on the object graph you've provided, you could probably accomplish this by XML serializing the first object, and XML deserializing the XML stream into the second object.
Your proposed Merger method could possibly look like this:
public class Merger
{
public static object Merge(object copyFrom, object copyTo)
{
var xmlContent = MyXMLSerializationMethod(copyFrom);
MyXMLDeserializationMethod(xmlContent, typeof(copyTo), out copyTo);
return copyTo;
}
}
Good post about using AutoMapper to solve this problem in the context of MVVM and MVC
http://www.bengtbe.com/blog/post/2009/04/14/Using-AutoMapper-to-map-view-models-in-ASPNET-MVC.aspx

Categories

Resources