2010-11-10 61 views
1

我们有两个类具有完全相同的公共访问器(和其中许多)但来自对象层次结构中不同区域的两个类;我们需要复制和比较这两个对象。我们可以手动编写一个拷贝构造函数和一个比较运算符来比较相同名称的访问器的值,但似乎好像有一种更好的方法来使用反射和LINQ来完成这个工作。干净的方法来比较/复制相似的类

例如:我们有ClassA,它有70个访问器;我们也有类ClassB,它具有70个访问器,它们被定义为与ClassA的访问器相同的名称和类型。

public class ClassA 
{ 
int OneInt {get; set;} 
int TwoInt {get; set;} 
... 
string OneString {get; set;} 
string AnotherString {get; set;} 
} 

public class ClassB 
{ 
int OneInt {get; set;} 
int TwoInt {get; set;} 
... 
string OneString {get; set} 
string AnotherString {get; set;} 
} 

我想什么是使用反射来发现所有的的ClassA公共访问器,并使用这些名称上ClassB的相应访问的值设置为访问者的价值的简单方法ClassA的。粗略地说,在伪代码:

foreach (string accName in ClassA.Accessors[]) 
    BInstance.Accessors[accName].Value = AInstance.Accessors[accName].Value; 

,当然,同样的事情可以用于两个类之间的测试平等。我对C#反射和LINQ的认识还不足以知道如何完成这个任务,但我发誓这是一个相对简单的事情。

回答

2

你粗略的伪代码有点准确。让我清理了一点:

foreach (var propertyA in typeof(ClassA).GetProperties()) 
{ 
    var propertyB = typeof(ClassB).GetProperty(propertyA.Name); 
    var valueA = propertyA.GetValue(objectA, null); 
    propertyB.SetValue(objectB, valueA, null); 
} 

显然,这不会做错误检查,和类似的东西,但它应该做的工作。

你可以在Linq做到,但我认为它不会更干净。

+0

我喜欢那个;这很清楚。我知道我和pcode在一起。 :) – 2010-11-10 18:36:10

+0

用于小修改;效果很好! – 2010-11-11 00:55:24

5

如何使用AutoMapper

Mapper.CreateMap<ClassA, ClassB>(); 

然后:

ClassA classA = ... 
ClassB classB = Mapper.Map<ClassA, ClassB>(classA); 

它基本上是你的伪代码的实现。

+0

不错;这绝对是一种选择,尽管我仍然怀疑有一种“巧妙”的方式可以在香草C#中完成这个任务。 – 2010-11-10 18:34:58

+0

当然是的,它会使用反射。但是,如果你想让它变得非常聪明(例如处理null的情况,不兼容的类型......),你需要编写大量的香草C#代码。那么为什么在某人已经完成它,测试它,记录它,将它打包在一个可重复使用的程序集中,测量它的性能时编写它,......以便现在可以专注于应用程序的真实业务,而不是进行管道安装? – 2010-11-10 18:36:24

+0

你的观点很好,但我认为即使他们可能已经在外部库中实现,学习技术也是有价值的;这是一个以实用的方式获得语言深度的问题。 – 2010-11-10 18:39:54