【问题标题】:Build an object from another object in C# using generic code使用通用代码从 C# 中的另一个对象构建一个对象
【发布时间】:2011-06-12 18:31:31
【问题描述】:

假设我有一个 User 类型的对象,如下所示:

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

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

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

使用完全通用的代码?意思是,我不想硬编码与类型或属性有关的任何内容,因为此代码需要应用于我网站上的每个实体。 (顺便说一下,“用户”类型是一个实体,所以如果它可以帮助您更好地编码,请使用它)。

我只是想为我遇到的问题想出一个解决方案,我相信Stub Entities 可以解决这个问题,但我需要这样做,而不需要对任何类型或属性进行硬编码。

【问题讨论】:

  • 这两种用户类型不同吗?
  • 不清楚您要做什么。两者的区别在于 Class 字段的存在。您想复制一个对象并删除任何名为“类”的字段还是想要更通用的东西?底线是你需要做一些反思。
  • 它们代表同一个实体。显然我的实体比这复杂得多,但基本上使用存根实体我相信我可以将部分对象保存到数据库中,但我想在保存之前删除任何设置为 NULL 的值。

标签: c# entity-framework generics reflection


【解决方案1】:

使用反射来实现:

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);
        }
    }
}

【讨论】:

    【解决方案2】:

    在这种情况下,泛型不会为您提供帮助。实体框架中可能有一些选项,但我对此并不了解。

    然而,使用反射是可能的。你可以试试这样的:

    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);
        }
    }
    

    请记住,这要求您要复制的所有属性都具有公共 setter 和 getter。 “深拷贝”与“浅拷贝”之间也存在差异,这意味着子对象是否也被复制或仅被引用。这个例子只会引用它们,所以它是一个“浅拷贝”

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-17
        • 1970-01-01
        相关资源
        最近更新 更多