使用通用代码从C#中的另一个对象构建对象

时间:2011-06-12 18:31:32

标签: c# entity-framework generics reflection

假设我有类型用户的对象,如下所示:

User {
   Name = "Bob",
   Email = "Bob@gmail.com",
   Class = NULL
}

任何人都可以想到一种方法来获取该对象并创建一个这样的对象:

User {
   Name = "Bob",
   Email = "Bob@gmail.com"
}

使用完全通用的代码?这意味着,我不想硬编码任何与Type或Properties相关的代码,因为这段代码需要应用于我网站上的每个实体。 (顺便说一句,“用户”类型是一个实体,所以如果它能帮助你更好地编码,请使用它)。

我只想尝试解决我遇到的问题并且我相信Stub Entities可以解决问题,但我需要在不对任何类型或属性进行硬编码的情况下进行解决。

3 个答案:

答案 0 :(得分:5)

使用反射来实现这一目标:

public void CopyValues<TSource, TTarget>(TSource source, TTarget target)
{
    var sourceProperties = typeof(TSource).GetProperties().Where(p => p.CanRead);

    foreach (var property in sourceProperties)
    {
        var targetProperty = typeof(TTarget).GetProperty(property.Name);

        if (targetProperty != null && targetProperty.CanWrite && targetProperty.PropertyType.IsAssignableFrom(property.PropertyType))
        {
            var value = property.GetValue(source, null);

            targetProperty.SetValue(target, value, null);
        }
    }
}

答案 1 :(得分:4)

对于这种情况,泛型不会帮助你。实体框架中可能有一些选项,但我并不知道。

然而,可以使用Reflection。你可以尝试这样的事情:

public static void CopyProperties(object a, object b)
{
    if (a.GetType() != b.GetType())
        throw new ArgumentException("Types of object a and b should be the same", "b")

    foreach (PropertyInfo property in a.GetType().GetProperties())
    {
        if (!property.CanRead || !property.CanWrite || (property.GetIndexParameters().Length > 0))
            continue;

        property.SetValue(b, property.GetValue(a, null), null);
    }
}

请注意,这需要您要复制的所有属性同时具有公共设置器和getter。 “深拷贝”与“浅拷贝”之间也存在差异,这意味着子对象也被复制或仅被引用。这个例子只会引用它们,因此它将是一个“浅拷贝”

答案 2 :(得分:2)

这看起来像是反思而不是泛型的问题(尽管泛型可以用作缓存反射策略的偷偷摸摸的方式)。除非我误读它,否则你想要创建一个新实例并复制大多数成员......哪种反射很擅长,尽管相对较慢。您可以使用元编程来提高速度;在第一次运行时(每个类型)生成一个优化版本,可能使用DynamicMethod或Expression,并存储一个类型化的委托。然后只需使用委托。