C# 在运行时将属性的属性从一个实例复制到另一个实例(不同类型)
假设我有两个这样的课程:C# 在运行时将属性的属性从一个实例复制到另一个实例(不同类型),c#,reflection,reflection.emit,C#,Reflection,Reflection.emit,假设我有两个这样的课程: 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 public
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
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;
}
是否可以在运行时将属性从foo复制到bar?属性不附加到实例,而是附加到类型定义
虽然可以在运行时使用反射创建新类型,但不能更改现有的类型定义。属性是(编译和加载的)程序集元数据的一部分,因此我认为您无法在运行时轻松修改它们 我能想到的唯一选择是使用CodeDOM生成带有属性的代码并重新编译(并重新加载程序集),或者使用
System.Reflection.Emit
(这是可能的,但非常复杂)
你为什么要这样做?也许有更简单的方法来解决您的问题…如果您需要属性来执行数据绑定或其他与UI相关的任务,您可以尝试更改TypeDescriptor的默认行为 看这里
您可以为类型添加自定义类型描述符,它允许您为某些使用TypeDescriptor.GetXXX成员的组件提供自定义属性,而不是直接使用类型元数据进行操作。这是否可行取决于哪些库需要查看属性。如果需要看到这一点的代码使用了反射,那么您就完了。你不能这么做 但是,;如果需要这样做的代码使用组件模型,这是可能的,但这需要大量的工作。您可以实现一个
TypeDescriptionProvider
,它创建一个每个实例ICustomTypeDescriptor
,并定义自定义链式属性描述器
实例。然后,您将补充(或替换)每个属性的属性,将它们传递到基本构造函数(或重写attributes属性)。结果是,以下内容将包括您的属性:
var attribs = TypeDescriptor.GetProperties(obj)["Name"].Attributes;
winforms数据绑定之类的东西使用这个API,但它不太关心您的自定义属性。请原谅我没有写一个完整的例子,但这是一个大量的工作;这些接口/基类型中没有一个是可以实现的。归根结底,我怀疑它是否值得。“复制”属性的概念已经过时了。但是,您可以在检查是否应用了属性的代码中执行一些有意义的操作。您可以使用另一个属性来告诉代码它应该使用另一种类型来验证[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;}
}
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
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;
}
检查属性的代码可能如下所示:
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
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;
}
请注意此代码如何允许链接属性提供程序。请查看AutoMapper。 AutoMapper是一个映射器框架,可以将DTO对象转换为域模型对象 简介信息: 二进制发布站点: 源代码发布站点:
我是否没有抓住要点? Wy是否不使用隐式运算符
Bus bus;
BigVehicle big = bus;
public static implicit operator Bigvehicle(Bus bus)
{
}
只是想确定一下,您是指Name的值还是指修饰Name属性的属性?您希望的输出是,Bar.Name将等于Foo.Name或该Bar.Name将用[Required]?@Elisha Bar修饰。Name将用Requiredwell修饰,基本上,我只是想知道是否有可能在创建某个实例之前或之后在运行时使用属性进行修饰type@Omu:否。至少没有很多反射魔法(例如,由自动实现接口的各种代理使用)。但是这样做有什么实际用途吗?所以这是可能的,我们现在需要的是一个知道如何做到这一点的人;实用的?是的,如果您需要在运行时装饰一些属性,那么这会有所帮助ya@Omu:会有很多限制,但根据使用情况,反射可能会解决问题。这就是为什么我要询问一些特定的信息——我知道您希望在运行时装饰属性。我只是不明白为什么…像这样的事情: