在一个应用程序中,我们有一组ORM对象和一组业务对象。大多数时候我们只是通过会员副本来做会员。其他时候我们稍微处理数据。例如:
tEmployee emp = new tEmployee();
emp.Name = obj.Name;
emp.LastName = obj.LastName;
emp.Age = obj.Age;
emp.LastEdited = obj.LastEdited.ToGMT();
现在这个工作得很好,并且速度很快,但在编码时并不完全简洁。我们的一些对象有多达40个成员,所以做这样的副本可能会变得相当繁琐。当然,你只需要两种方法来进行双转换,但我想找到一种更好的方法来做到这一点。
反射是一种自然的选择,但在基准测试中,我发现使用反射时执行时间大约慢了100倍。
有没有更好的方法来解决这个问题?
澄清: 我正在从一种类型转换为另一种类型。在上面的例子中,obj的类型为BLogicEmployee,emp的类型为tEmployee。他们共享成员名称,但就是这样。
答案 0 :(得分:5)
您可能需要查看AutoMapper。
答案 1 :(得分:3)
如果你不介意第一次编译lambda表达式时它有点慢:
public static class Copier<T>
{
private static readonly Action<T, T> _copier;
static Copier()
{
var x = Expression.Parameter(typeof(T), "x");
var y = Expression.Parameter(typeof(T), "y");
var expressions = new List<Expression>();
foreach (var property in typeof(T).GetProperties())
{
if (property.CanWrite)
{
var xProp = Expression.Property(x, property);
var yProp = Expression.Property(y, property);
expressions.Add(Expression.Assign(yProp, xProp));
}
}
var block = Expression.Block(expressions);
var lambda = Expression.Lambda<Action<T, T>>(block, x, y);
_copier = lambda.Compile();
}
public static void CopyTo(T from, T to)
{
_copier(from, to);
}
}
答案 2 :(得分:2)
如果你使用代表,反思可以加速很多。基本上,您可以为每个getter / setter对创建一对委托,然后执行这些委托 - 它很可能非常。使用Delegate.CreateDelegate
创建一个给定MethodInfo
等的委托。或者,您可以使用表达式树。
如果你正在创建一个 new 对象,我已经有了一堆代码在MiscUtil中执行此操作。 (它位于MiscUtil.Reflection.PropertyCopy
类中。)它使用反射将属性复制到现有对象中,但使用委托将对象转换为新对象。显然,你可以根据自己的需要进行调整。我敢肯定,如果我现在正在写它,我可以避免使用Delegate.CreateDelegate
进行复制的反射,但我不打算改变它:)
答案 3 :(得分:2)
考虑使用AutoMapper。从其文档:
..只要AutoMapper效果最好 成员的名字最多匹配 源类型的成员。如果你有 一个名为“FirstName”的源成员, 这将自动映射到a 目的地成员的名字 “姓”。
这将为您节省大量的显式映射,AutoMapper当然允许自定义特定的映射:
Mapper.CreateMap<Model.User, Api.UserInfo>()
.ForMember(s => s.Address, opt => opt.Ignore())
.ForMember(s => s.Uri, opt => opt.MapFrom(c => HttpEndpoint.GetURI(c)))
答案 4 :(得分:1)
Object.MemberwiseClone可能会有用。不确定它的性能如何,显然任何复杂的对象都需要额外的处理来确保正确的复制。
答案 5 :(得分:0)
看看您是否可以使用this
回顾: 和class必须是Serializable才能工作。
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
答案 6 :(得分:0)
看看自动映射器,如果你的字段匹配,它可以自动映射你的对象......