2

假设我有 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 ?

4

7 回答 7

8

属性不附加到实例——它们附加到类型定义。

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

于 2010-06-14T14:01:24.090 回答
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;
    }

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

于 2010-06-18T06:14:43.637 回答
3

这是否可能取决于哪些库需要查看该属性。如果需要看到这个的代码使用了反射,那么你就完蛋了。你不能这样做。

然而; 如果需要这个的代码使用组件模型,这是可能的- 但这是很多工作。您可以实现 aTypeDescriptionProvider创建一个 per-instanceICustomTypeDescriptor并定义自定义链式PropertyDescriptor实例。然后,您将补充(或替换)每个属性的属性,将它们传递给基本构造函数(或覆盖属性属性)。结果是以下内容将包含您的属性:

var attribs = TypeDescriptor.GetProperties(obj)["Name"].Attributes;

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

于 2010-06-17T21:17:40.730 回答
2

属性是(编译和加载的)程序集元数据的一部分,所以我认为你不能在运行时轻易地修改它们。

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

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

于 2010-06-14T14:01:49.077 回答
0

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

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

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

于 2010-06-17T17:09:34.633 回答
0

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

Bus bus;
BigVehicle big = bus;

public static implicit operator Bigvehicle(Bus bus)
{

}
于 2010-08-16T16:03:15.207 回答
-5

请看一下 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/

于 2010-06-23T17:27:54.317 回答