问题描述
任何人有这从一个对象值映射到另一个很好的工具类建议?我想使用反射,并采取从第一对象两个对象,并复制值的第二一个工具类,如果不存在具有相同名称的公共财产。
Anyone have a suggestion for a good utility class that maps values from one object to another? I want a utility class that uses reflection and takes two objects and copies values from the 1st object to the second if there is a public property with the same name.
我有从Web服务代理产生的两个实体,所以我不能改变父类或impliment像一个接口或任何东西。但我知道,这两个对象具有相同的公共属性。
I have two entities that are generated from a web service proxy, so I can't change the parent class or impliment an interface or anything like that. But I know that the two objects have the same public properties.
推荐答案
乔恩斯基特和Marc Gravell有一个名为库的。在 MiscUtil.Reflection
有一类称为 PropertyCopy
这不正是你的描述。它仅适用于.NET 3.5。
Jon Skeet and Marc Gravell have a library called MiscUtil. Inside MiscUtil.Reflection
there is a class called PropertyCopy
that does exactly what you describe. It only works for .NET 3.5.
它的工作原理是在SourceType中的公共属性运行,用的TargetType的公共属性名称匹配起来,可以确保每个属性可以从源到目标被分配,然后创建并缓存复印机功能对于这两种类型(所以你不要做这一切的反思每一次)。我用它在生产中code和可以保证它的善良。
It works by running over the public properties of the SourceType, matches them up by name with the public properties of the TargetType, makes sure that each property can be assigned from the source to the target and then creates and caches a copier function for those two types (so you don't do all this reflection every time). I've used it in production code and can vouch for its goodness.
什么哎,我想我只是张贴的及其的简洁code(这是少于100行瓦特/评论)。在这里为这个code牌照可以发现的:
What the hey, I figured I'd just post their concise code (it's less than 100 lines w/comments). The license for this code can be found here:
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
namespace MiscUtil.Reflection
{
/// <summary>
/// Generic class which copies to its target type from a source
/// type specified in the Copy method. The types are specified
/// separately to take advantage of type inference on generic
/// method arguments.
/// </summary>
public static class PropertyCopy<TTarget> where TTarget : class, new()
{
/// <summary>
/// Copies all readable properties from the source to a new instance
/// of TTarget.
/// </summary>
public static TTarget CopyFrom<TSource>(TSource source) where TSource : class
{
return PropertyCopier<TSource>.Copy(source);
}
/// <summary>
/// Static class to efficiently store the compiled delegate which can
/// do the copying. We need a bit of work to ensure that exceptions are
/// appropriately propagated, as the exception is generated at type initialization
/// time, but we wish it to be thrown as an ArgumentException.
/// </summary>
private static class PropertyCopier<TSource> where TSource : class
{
private static readonly Func<TSource, TTarget> copier;
private static readonly Exception initializationException;
internal static TTarget Copy(TSource source)
{
if (initializationException != null)
{
throw initializationException;
}
if (source == null)
{
throw new ArgumentNullException("source");
}
return copier(source);
}
static PropertyCopier()
{
try
{
copier = BuildCopier();
initializationException = null;
}
catch (Exception e)
{
copier = null;
initializationException = e;
}
}
private static Func<TSource, TTarget> BuildCopier()
{
ParameterExpression sourceParameter = Expression.Parameter(typeof(TSource), "source");
var bindings = new List<MemberBinding>();
foreach (PropertyInfo sourceProperty in typeof(TSource).GetProperties())
{
if (!sourceProperty.CanRead)
{
continue;
}
PropertyInfo targetProperty = typeof(TTarget).GetProperty(sourceProperty.Name);
if (targetProperty == null)
{
throw new ArgumentException("Property " + sourceProperty.Name + " is not present and accessible in " + typeof(TTarget).FullName);
}
if (!targetProperty.CanWrite)
{
throw new ArgumentException("Property " + sourceProperty.Name + " is not writable in " + typeof(TTarget).FullName);
}
if (!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
{
throw new ArgumentException("Property " + sourceProperty.Name + " has an incompatible type in " + typeof(TTarget).FullName);
}
bindings.Add(Expression.Bind(targetProperty, Expression.Property(sourceParameter, sourceProperty)));
}
Expression initializer = Expression.MemberInit(Expression.New(typeof(TTarget)), bindings);
return Expression.Lambda<Func<TSource,TTarget>>(initializer, sourceParameter).Compile();
}
}
}
}
这篇关于复制的值从一个对象到另一的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!