Reflection Emit:如何将Attribute实例转换为CustomAttributeBuilder或CustomAttributeData

Ofi*_*fir 5 c# reflection reflection.emit

我创建了一个生成器类,它基于实现接口的接口构建代理类.

请参阅我在基于接口构建代理类的帖子而不实现它.

我很熟悉CustomAttributeData.GetCustomAttributes(MemberInfo target),当我读取Interface的成员并成功将它们导入代理时,我使用它.

我想在运行时向生成的类注入其他属性.我要求将属性实例注入代理中.

例如:

开发人员可以将其作为值传递:new ObsoleteAttribute("Demo", true),(它有一个空构造函数,但属性是只读的),我想将其转换为:

return new CustomAttributeBuilder(
               attribute.GetType().GetConstructor(Type[] {typeof (string), typeof (bool)}),
               new object[] {"Demo", true},
               new FieldInfo[0], 
               new object[0]);
Run Code Online (Sandbox Code Playgroud)

记住,我不知道给出了什么.

Joe*_*ger 5

这不是一个通用的解决方案,但如果您愿意将您支持的属性限制为具有无参数构造函数和读/写属性和字段的属性,它将起作用

CustomAttributeBuilder BuildCustomAttribute(System.Attribute attribute)
{
    Type type = attribute.GetType();
    var constructor = type.GetConstructor(Type.EmptyTypes);
    var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);

    var propertyValues = from p in properties
                         select p.GetValue(attribute, null);
    var fieldValues = from f in fields
                      select f.GetValue(attribute);

    return new CustomAttributeBuilder(constructor, 
                                     Type.EmptyTypes,
                                     properties,
                                     propertyValues.ToArray(),
                                     fields,
                                     fieldValues.ToArray());
}
Run Code Online (Sandbox Code Playgroud)

要进行通用解决方案,您可以使用表达式。那更复杂,但会允许像这样的语法:

BuildCustomAttribute(() => new ObsoleteAttribute("Demo", true));
Run Code Online (Sandbox Code Playgroud)

解析表达式以提取构造函数信息和参数将是复杂的部分,但它可以完成。

CustomAttributeBuilder BuildCustomAttribute(Expression<Action> exp)
{
    //extract ConstructorInfo from exp
    //extract ParameterValues from exp
    //extract Attribute Type from exp

    return new CustomAttributeBuilder(ConstructorInfo, ParameterValues);
}
Run Code Online (Sandbox Code Playgroud)

  • 同样,这需要大量工作才能让您的开发人员无需了解 CustomAttributeBuilder 的工作原理.... (2认同)