Assume the following class:
public class MyEntity
{
public string FirstName;
public string LastName;
}
I would like to compare two instances of MyEntity
, and create a new MyEntity
instance that contains only the differences in values between the two other instances. Properties that are equal will result a null
value in the new object.
for example, the I would like the following code:
MyEntity entity1 = new MyEntity() { FirstName = "Jon", LastName = "Doh" };
MyEntity entity2 = new MyEntity() { FirstName = "Jon", LastName = "The Great" };
MyEntity diffEntity = CreateDiffEntity(entity1, entity2); // TODO
to result with the following diffEntity
values:
{
FirstName: null,
LastName: "The Great"
}
We can assume that all properties are nullable.
In case the values don't match, the new object should contain the value of the second object's property.
Please assume I have many types of entities, with different properties definitionsm
So I need a solution that can be used on other class types than MyEntity
, and that won't require changes when new properties are added to the classes.
The final goal is to enable a client mobile application to send a DTO that contains only the changes made to an entity, to a ASP.NET MVC WebAPI server application.
How can this be properly done?
You could use Reflection to solve this. The basic gist of it is:
public void Compare(object first,object second, object result)
{
Type t = first.GetType();
PropertyInfo[] propertyInfoList = t.GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfoList)
{
object value1= propertyInfo.GetValue(first, null);
object value2 = propertyInfo.GetValue(second, null);
if (value1 != value2)
{
propertyInfo.SetValue(result, value1, null);
}
else
{
propertyInfo.SetValue(result, null, null);
}
}
}
And then use it like this:
MyType result = new MyType();
Compare(object1,object2, result);
It could be used as an extension method or a member on one of your entities.
There's a big problem with this whole approach: you can't set anything to null
. You should probably just be sending the full entity or, if you have interface(s) that only allow editing a subset of the properties, make a DTO for each interface with just the changes that can happen there.
Anyway, just because it was ripe for some easy improvement, this is a generic, and slightly modified, solution based on BrianV's solution . (using object.Equals
instead of !=
allows for things to be compared by their values, not just their identities)
public T Compare<T>(T first, T second) where T : new()
{
T result = new T();
Type t = typeof(T);
PropertyInfo[] propertyInfoList = t.GetProperties();
foreach (PropertyInfo propertyInfo in propertyInfoList)
{
object value1 = propertyInfo.GetValue(first, null);
object value2 = propertyInfo.GetValue(second, null);
if (!object.Equals(value1, value2))
propertyInfo.SetValue(result, value2, null);
}
return result;
}
Use it like:
MyEntity entity1 = new MyEntity() { FirstName = "Jon", LastName = "Doh" };
MyEntity entity2 = new MyEntity() { FirstName = "Jon", LastName = "The Great" };
MyEntity diffEntity = Compare(entity1, entity2);
Here you go:
static public T CreateDiffEntity<T>(T entity1, T entity2) where T : new()
{
T result = new T();
foreach (var property in typeof(T).GetProperties())
{
var valuePropertyEntity1 = property.GetValue(entity1);
var valuePropertyEntity2 = property.GetValue(entity2);
if (!valuePropertyEntity1.Equals(valuePropertyEntity2))
property.SetValue(result, valuePropertyEntity2);
else
property.SetValue(result, null);
}
return result;
}
You can solve your issue like this:
public MyEntity CreateDiffEntity(MyEntity entity1, MyEntity entity2) {
MyEntity diff = new MyEntity();
diff.FirstName = !entity1.FirstName.equals(entity2.FirstName) ? entity2.FirstName : string.Empty;
diff.LastName = !entity1.LastName.equals(entity2.LastName) ? entity2.LastName : string.Empty;
return diff;
}
you can do it in the object initializer
MyEntity entity1 = new MyEntity() { FirstName = "Jon", LastName = "Doh" };
MyEntity entity2 = new MyEntity() { FirstName = "Jon", LastName = "The Great" };
MyEntity diffEntity = new MyEntity
{
FirstName = (entity1.FirstName == entity2.FirstName) ? null : entity2.FirstName,
LastName = (entity1.LastName == entity2.LastName) ? null : entity2.LastName
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.