using System;
using System.Reflection;
using System.Linq.Expressions;
public class TestDTO
{
public string StringValue { get; set; }
public int IntValue { get; set; }
}
public class TestDataClass
{
public string StringValue { get; set; }
public int IntValue { get; set; }
public string AnotherStringValue { get; set;}
}
public class Test
{
public static bool AreEqual<TDTO, TDATA>(TDTO dto, TDATA data)
{
foreach(var prop in typeof(TDTO).GetProperties())
{
var dataProp = typeof(TDATA).GetProperty(prop.Name);
if (dataProp == null)
throw new InvalidOperationException(string.Format("Property {0} is missing in data class.", prop.Name));
var compExpr = GetComparisonExpression(prop, dataProp);
var del = compExpr.Compile();
if (!(bool)del.DynamicInvoke(dto, data))
return false;
}
return true;
}
private static LambdaExpression GetComparisonExpression(PropertyInfo dtoProp, PropertyInfo dataProp)
{
var dtoParam = Expression.Parameter(dtoProp.DeclaringType, "dto");
var dataParam = Expression.Parameter(dataProp.DeclaringType, "data");
return Expression.Lambda(
Expression.MakeBinary(ExpressionType.Equal,
Expression.MakeMemberAccess(
dtoParam, dtoProp),
Expression.MakeMemberAccess(
dataParam, dataProp)), dtoParam, dataParam);
}
public static void Main()
{
var dto = new TestDTO() { StringValue = "Test", IntValue = 1 };
var data = new TestDataClass() { StringValue = "Test", IntValue = 1 };
Console.WriteLine("AreEqual = {0}", AreEqual(dto, data));
var otherData = new TestDataClass() { StringValue = "SomeOtherValue", IntValue = 3 };
Console.WriteLine("AreEqual = {0}", AreEqual(dto, otherData));
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uUmVmbGVjdGlvbjsKdXNpbmcgU3lzdGVtLkxpbnEuRXhwcmVzc2lvbnM7CgpwdWJsaWMgY2xhc3MgVGVzdERUTwp7CglwdWJsaWMgc3RyaW5nIFN0cmluZ1ZhbHVlIHsgZ2V0OyBzZXQ7IH0KCXB1YmxpYyBpbnQgSW50VmFsdWUgeyBnZXQ7IHNldDsgfQp9CgpwdWJsaWMgY2xhc3MgVGVzdERhdGFDbGFzcwp7CglwdWJsaWMgc3RyaW5nIFN0cmluZ1ZhbHVlIHsgZ2V0OyBzZXQ7IH0KCXB1YmxpYyBpbnQgSW50VmFsdWUgeyBnZXQ7IHNldDsgfQoJcHVibGljIHN0cmluZyBBbm90aGVyU3RyaW5nVmFsdWUgeyBnZXQ7IHNldDt9Cn0KCnB1YmxpYyBjbGFzcyBUZXN0CnsKCXB1YmxpYyBzdGF0aWMgYm9vbCBBcmVFcXVhbDxURFRPLCBUREFUQT4oVERUTyBkdG8sIFREQVRBIGRhdGEpIAoJewoJCWZvcmVhY2godmFyIHByb3AgaW4gdHlwZW9mKFREVE8pLkdldFByb3BlcnRpZXMoKSkKCQl7CgkJCXZhciBkYXRhUHJvcCA9IHR5cGVvZihUREFUQSkuR2V0UHJvcGVydHkocHJvcC5OYW1lKTsKCQkJaWYgKGRhdGFQcm9wID09IG51bGwpCgkJCQl0aHJvdyBuZXcgSW52YWxpZE9wZXJhdGlvbkV4Y2VwdGlvbihzdHJpbmcuRm9ybWF0KCJQcm9wZXJ0eSB7MH0gaXMgbWlzc2luZyBpbiBkYXRhIGNsYXNzLiIsIHByb3AuTmFtZSkpOwoJCQl2YXIgY29tcEV4cHIgPSBHZXRDb21wYXJpc29uRXhwcmVzc2lvbihwcm9wLCBkYXRhUHJvcCk7CgkJCXZhciBkZWwgPSBjb21wRXhwci5Db21waWxlKCk7CgkJCWlmICghKGJvb2wpZGVsLkR5bmFtaWNJbnZva2UoZHRvLCBkYXRhKSkKCQkJCXJldHVybiBmYWxzZTsKCQl9CgkJcmV0dXJuIHRydWU7Cgl9CgkKCXByaXZhdGUgc3RhdGljIExhbWJkYUV4cHJlc3Npb24gR2V0Q29tcGFyaXNvbkV4cHJlc3Npb24oUHJvcGVydHlJbmZvIGR0b1Byb3AsIFByb3BlcnR5SW5mbyBkYXRhUHJvcCkKCXsKCQl2YXIgZHRvUGFyYW0gPSBFeHByZXNzaW9uLlBhcmFtZXRlcihkdG9Qcm9wLkRlY2xhcmluZ1R5cGUsICJkdG8iKTsKCQl2YXIgZGF0YVBhcmFtID0gRXhwcmVzc2lvbi5QYXJhbWV0ZXIoZGF0YVByb3AuRGVjbGFyaW5nVHlwZSwgImRhdGEiKTsKCQlyZXR1cm4gRXhwcmVzc2lvbi5MYW1iZGEoCgkJCUV4cHJlc3Npb24uTWFrZUJpbmFyeShFeHByZXNzaW9uVHlwZS5FcXVhbCwgCgkJCQlFeHByZXNzaW9uLk1ha2VNZW1iZXJBY2Nlc3MoCgkJCQkJZHRvUGFyYW0sIGR0b1Byb3ApLCAKCQkJCUV4cHJlc3Npb24uTWFrZU1lbWJlckFjY2VzcygKCQkJCQlkYXRhUGFyYW0sIGRhdGFQcm9wKSksIGR0b1BhcmFtLCBkYXRhUGFyYW0pOwoJfQoJCglwdWJsaWMgc3RhdGljIHZvaWQgTWFpbigpCgl7CgkJdmFyIGR0byA9IG5ldyBUZXN0RFRPKCkgeyBTdHJpbmdWYWx1ZSA9ICJUZXN0IiwgSW50VmFsdWUgPSAxIH07CgkJdmFyIGRhdGEgPSBuZXcgVGVzdERhdGFDbGFzcygpIHsgU3RyaW5nVmFsdWUgPSAiVGVzdCIsIEludFZhbHVlID0gMSB9OwoJCUNvbnNvbGUuV3JpdGVMaW5lKCJBcmVFcXVhbCA9IHswfSIsIEFyZUVxdWFsKGR0bywgZGF0YSkpOwoJCXZhciBvdGhlckRhdGEgPSBuZXcgVGVzdERhdGFDbGFzcygpIHsgU3RyaW5nVmFsdWUgPSAiU29tZU90aGVyVmFsdWUiLCBJbnRWYWx1ZSA9IDMgfTsKCQlDb25zb2xlLldyaXRlTGluZSgiQXJlRXF1YWwgPSB7MH0iLCBBcmVFcXVhbChkdG8sIG90aGVyRGF0YSkpOwoJfQp9