假设我有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?
答案 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://automapper.codeplex.com