在运行时将属性的属性从一个实例复制到另一个实例(不同类型)

时间:2010-06-14 13:57:37

标签: c# reflection reflection.emit

假设我有2个这样的课程:

public class Foo
{
[Required]
public string Name {get;set;}
}

public class Bar 
{
// put here [Required] at run-time
public string Name {get;set;}
}

var foo = new Foo();
var bar = new Bar();
//copy the required from foo to bar

是否可以在运行时将属性从foo复制到bar?

7 个答案:

答案 0 :(得分:8)

属性未附加到实例 - 它们附加到类型定义。

虽然您可以使用反射在运行时创建新类型,但您无法更改现有的类型定义。

答案 1 :(得分:4)

“复制”属性的概念已经出来。但是,您可以在代码中执行一些有意义的操作,以检查是否应用了该属性。您可以使用另一个属性来告诉代码它应该使用另一种类型来验证[Required]属性。例如:

[AttributeUsage(AttributeTargets.Class)]
public class AttributeProviderAttribute : Attribute {
    public AttributeProviderAttribute(Type t) { Type = t; }
    public Type Type { get; set; }
}

您可以这样使用:

public class Foo {
    [Required]
    public string Name { get; set; }
}

[AttributeProvider(typeof(Foo))]
public class Bar {
    public string Name { get; set; }
}

检查属性的代码可能如下所示:

    static bool IsRequiredProperty(Type t, string name) {
        PropertyInfo pi = t.GetProperty(name);
        if (pi == null) throw new ArgumentException();
        // First check if present on property as-is
        if (pi.GetCustomAttributes(typeof(RequiredAttribute), false).Length > 0) return true;
        // Then check if it is "inherited" from another type
        var prov = t.GetCustomAttributes(typeof(AttributeProviderAttribute), false);
        if (prov.Length > 0) {
            t = (prov[0] as AttributeProviderAttribute).Type;
            return IsRequiredProperty(t, name);
        }
        return false;
    }

请注意此代码如何允许链接属性提供程序。

答案 2 :(得分:3)

这是否可行取决于哪些库需要查看属性。如果需要查看此代码的代码使用 reflection ,那么您就会被打败。你不能这样做。

然而;如果需要它的代码使用组件模型,那么可能 - 但它是很多的工作。您可以实现创建每个实例TypeDescriptionProvider的{​​{1}},并定义自定义链接ICustomTypeDescriptor实例。然后,您将为每个属性补充(或替换)属性,将它们传递给基础构造函数(或覆盖attributes属性)。结果是,以下内容将包含您的属性:

PropertyDescriptor

winforms数据绑定之类的东西使用这个API,但它不会太在意你的自定义属性。你原谅我不会写一个完整的例子,但这是一个很多的工作;这些接口/基类型中没有一个是微不足道的。最终,我怀疑这是值得的。

答案 3 :(得分:2)

属性是(编译和加载)程序集的元数据的一部分,因此我认为您无法在运行时轻松修改它们。

我能想到的唯一选择是使用CodeDOM生成具有该属性的代码并重新编译它(并重新加载程序集),或者使用System.Reflection.Emit执行相同的操作(这是可能的,但是非常复杂)。

你为什么要这样做?也许有一种更简单的方法来解决你的问题......

答案 4 :(得分:0)

如果您需要属性来执行数据绑定或与UI相关的其他任务,您可以尝试更改TypeDescriptor的默认行为。

在这里查看http://msdn.microsoft.com/en-us/library/ms171819.aspx

您可以为类型添加自定义类型描述符,它允许您为使用TypeDescriptor.GetXXX成员而不是直接使用类型元数据操作的某些组件提供自定义属性。

答案 5 :(得分:0)

我在这里错过了这一点吗? 为什么不使用隐式运算符?

Bus bus;
BigVehicle big = bus;

public static implicit operator Bigvehicle(Bus bus)
{

}

答案 6 :(得分:-4)

请查看AutoMapper。 AutoMapper是一个映射器框架,可以将DTO对象转换为域模型对象。

简介信息: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx

二进制发布网站: http://automapper.codeplex.com

源代码发布网站: http://code.google.com/p/automapperhome/