2017-04-04 141 views
0

我在这里看到过一些类似的线程,但没有一个能够解答我的问题,而且我现在挣扎得不得不现在去问。有没有办法在C#中比较两种不同类型的对象#

我有两个对象,一个叫做Customer,另一个叫数据传输对象,叫做customerDto。

客户:

public partial class Customer 
{ 
    [DataMember] 
    public int Id { get; set;} 
    [DataMember] 
    public string Title { get; set;} 
    [DataMember] 
    public string FirstName { get; set;} 
    [DataMember] 
    public string Middle { get; set;} 
    [DataMember] 
    public string LastName { get; set;} 
    [DataMember] 
    public string Email { get; set;} 
    [DataMember] 
    public string HomePhone { get; set;} 
    [DataMember] 
    public string MobilePhone { get; set;} 
    [DataMember] 
    public string AddressLine1 { get; set;} 
    [DataMember] 
    public string AddressLine2 { get; set;} 
    [DataMember] 
    public string PostCode { get; set;} 
    [DataMember] 
    public DateTime? DateOfBirth { get; set;} 
    [DataMember][DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
    public string FullName { get; private set;} 
    } 

public partial class Customer 
{ 
    public virtual ICollection<DeliveryDetail> DeliveryDetails { get; set; } 
    public virtual ICollection<Order> Order { get; set; } 
} 

CustomerDto:

public class CustomerDto : ICloneable 
{ 
    public int Id { get; set; } 
    public string AddressLine1 { get; set; } 
    public string AddressLine2 { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 
    public string PostCode { get; set; } 
    public string Title { get; set; } 
    public string Email { get; set; } 
    public string HomePhone { get; set; } 
    public string MobilePhone { get; set; } 
    public DateTime? DateOfBirth { get; set; } 
} 

我需要比较他们分享的特性,但我不想写多行的if语句,因为这是凌乱。有没有办法做到这一点?

我只需要查看它们共享的任何属性是否有差异。如果一个不同,那么我们可以推进和更新客户。

在此先感谢。

+2

为什么不制作它的一个子类,并在该元素上进行比较? –

+4

你也可以使用反射来比较具有相同名称的字段,但我认为它可能更好的子类化或制作接口 – Pikoh

回答

1

我认为你在这里找的是一个使用反射的foreach循环。

Customer customer; // assume its initialized 
CustomerDto custDTO; 
var recordsAreDifferent = false; 
foreach (var prop in custDTO.GetType().GetProperties()) 
{ 
    PropertyInfo customerProperty = customer.GetType().GetProperty(prop.name); 
    if(customerProperty == null) {continue;} 
if(!prop.GetValue(custDTO, null).Equals(customerProperty.GetValue(customer, null)) { 
    recordsAreDifferent = true; 
    } 
} 
+1

就像一个更清洁的加法,我会'Dictionary > differences' where I将有关键字作为字段和两个字符串作为当前和比较 –

1

您可以在使用反射泛型方法做到这一点:

public static bool CompareMatchingProperties<TLeft,TRight>(TLeft lhs, TRight rhs) { 
    var allLeft = typeof(TLeft).GetProperties().ToDictionary(p => p.Name); 
    var allRight = typeof(TRight).GetProperties().ToDictionary(p => p.Name); 
    foreach (var name in allLeft.Keys.Intersect(allRight.Keys)) { 
     if (!object.Equals(allLeft[name].GetValue(lhs), allRight[name].GetValue(rhs))) { 
      return false; 
     } 
    } 
    return true; 
} 

的想法是让双方从类型的所有公共属性(见allLeftallRight字典)构建的交集他们的名字(循环中的allLeft.Keys.Intersect(allRight.Keys)),从每个被比较的对象(allLeft[name].GetValue(lhs)allRight[name].GetValue(rhs))获得属性值,并使用object.Equals进行比较。

Demo.

有一两件事要记住使用任何这类方法的缺点是不具有任何公共的属性比较两个对象的结果将返回true。您可以通过至少要求一对属性匹配来解决该问题。

+0

我也会考虑创建一个'TryCompare ...',它返回一个不同的解释字典...看到其他答案的评论 –

1

您可以考虑客户类实现IComparable接口并实现CompareTo(Object obj)方法。

或者

实施IEquatable interface

+0

除他不想要手动写出所有对不同属性的检查。 – victor

+1

处理运行时错误是因为反射过程中发生的事情比编写(非常快速但冗长)的IComparable实现要困难得多。 – Scott

+0

这就是我说的方式你可以考虑 - 让他决定。 – jjj

0

你可以写这样的具体方法:

public bool UpdateCustomer(Customer customer, CustomerDto dto) 
    { 
     //Get properties from both objects 
     System.Reflection.PropertyInfo[] customerProperties = customer.GetType().GetProperties(); 
     System.Reflection.PropertyInfo[] dtoProperties = dto.GetType().GetProperties(); 

     //Get properties that have the same name on both objects 
     var propertiesToCompare = from customerProp in customerProperties 
            join dtoProp in dtoProperties 
            on customerProp.Name equals dtoProp.Name 
            select customerProp; 

     foreach (var property in propertiesToCompare) 
     { 
      if (property.GetValue(customer, null) != property.GetValue(dto, null)) 
       return true; 
     } 
     return false; 
    } 

你得到来自你的对象的所有属性,那么你检查是否有它们共享属性有不同的价值。如果他们这样做,该方法返回true。如果不是,则返回false。

0

据我所知,CustomerDto是DB的实体,Customer是客户的合同。将Customer类型转换为CustomerDto并比较CustomerDto的两个对象怎么样?

0

如果您需要比较2个对象,并且您正在使用C#,我认为一个很好的方法是使用运算符重载。要做到这一点,你这样考虑几点:

  • 所有操作符重载是静态方法
  • 你有一元运算符和二元运算。
  • 若要使比较运算符过载(< <,>>,==,!=,>,<,> =,< =)您必须重载相反的运算符。 (例如,如果你负担“>”也必须超载“<”)
  • 你必须在涉及的对象的一些类中声明它。

sintaxis就是这样。

public static ReturnValue operator+(Object a, Object b) 
    { 
     // Comparison logic 
     return value; 

    } 

为了您的具体问题,你应该做这样的事情:

public static Boolean operator==(Customer cust, CustomerDto custDto) 
{ 
    //Here you code a for or foreach o whatever you want to compare 
    //cust with custDto and return true is you found a difference or false 
    //if there are no differences 

    return booleanValue; 
} 

然后ovearload =操作!重用代码,你可以回想一下其他比较:

public static Boolean operator!=(Customer cust, CustomerDto custDto) 
    { 
     return !(cust == custDto); 
    } 

因此,在你的代码,你可以检查是否有与这样的一个客户对象和一个CustomerDto对象之间的区别:

if (customerObject == customerDtoObject) 
{ 
    //Whatever you want 
} 

希望这会帮助你。

相关问题