从动态生成的类获取属性 [英] Get Attribute from Dynamically generated Class

查看:61
本文介绍了从动态生成的类获取属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,通常看起来像是相同问题的解决方案都无法解决.

I have run in to a little bit of a problem which is not solved by the generally available solutions to seemingly the same problem.

考虑:

我有一组动态生成的类,它们是从已知的基类继承的(我们称其为 BaseClass ).这些动态生成的类还具有动态生成的具有相关属性的 Properties .

I have a set of dynamically generated classes, inheriting from a known base Class (lets call it BaseClass). These dynamically generated classes also have dynamically generated Properties with associated attributes.

属性也属于自定义类,尽管不是动态生成的:

The attributes are also of a custom class, though not dynamically generated:

[AttributeUsage(AttributeTargets.Property)]
class TypeAttribute: Attribute
{
    private Type _type;
    public Type Type
    {
        get { return _type; }
    }

    public TypeAttribute(Type t)
    {
        _type = t;
    }
}

然后,我当然想在运行时获取此已分配属性的值:

Then I want to, runtime of course, fetch the value of this assigned attribute:

List<PropertyInfo> result = target.GetType()
  .GetProperties()
  .Where(
     p =>
        p.GetCustomAttributes(typeof(TypeAttribute), true)
        //.Where(ca => ((TypeAttribute)ca).)
        .Any()
     )
  .ToList();

其中 target BaseClass 的子类.但是,列表结果为空,这使我感到困惑.

where target is a subclass of BaseClass. The List result is however empty, and this baffles me.

我使用添加属性

PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, 
           PropertyAttributes.HasDefault, propertyType, null);
ConstructorInfo classCtorInfo = typeof(TypeAttribute).
           GetConstructor(new Type[] { typeof(Type) });
CustomAttributeBuilder myCABuilder = new CustomAttributeBuilder(
           classCtorInfo, new object[] { getType(dataType) });
propertyBuilder.SetCustomAttribute(myCABuilder);

其中 dataType 是要存储在属性中的类型,而 tb 是该类的 TypeBuilder .

where dataType is the type to store in the attribute and tb is the TypeBuilder for the class.

如果我对该属性执行 getCustomAttributes(),我将获得期望的属性,除了我要查找的属性.但是,如果我执行 getCustomAttributesData(),我会得到所有的信息,但是我要查找的是类型为 CustomAttributeData 的类型,并且无法转换为 TypeAttribute (如果我在VS调试器中检查实例,则可以看到其中包含的信息用于 TypeAttribute ).我猜这是问题的征兆,但我找不到原因-更不用说解决了.

If I do getCustomAttributes() on the property, I get the expected attributes except the one I'm looking for. But if I do getCustomAttributesData() I get all of them, but the one I'm looking for is of type CustomAttributeData and is not castable to TypeAttribute (if i examine the instance in the VS debugger i can see that the contained information is for a TypeAttribute). I'm guessing that this is a symptom of the problem, but I cannot find the cause - much less the solution.

有人可以告诉我为什么 result 列表为空吗?

Can anybody point out to me why the result list is empty?

推荐答案

对我来说很好;您确定您的属性和getter或setter方法存在的程度足以使其实际显示为属性吗?

Works fine for me; are you sure your property and getter or setter method(s) exist sufficiently that it actually shows as a property?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
[AttributeUsage(AttributeTargets.Property)]
public class TypeAttribute : Attribute
{
    private Type _type;
    public Type Type
    {
        get { return _type; }
    }

    public TypeAttribute(Type t)
    {
        _type = t;
    }
}

public class BaseClass
{

}

static class Program
{
    static void Main()
    {
        var aName = new AssemblyName("MyAssembly");
        var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(
                aName, AssemblyBuilderAccess.RunAndSave);
        var mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
        var tb = mb.DefineType("MyType", TypeAttributes.Public, typeof(BaseClass));

        var propertyName = "MyProperty";
        var propertyType = typeof(int);
        var propertyBuilder = tb.DefineProperty(propertyName,
           PropertyAttributes.HasDefault, propertyType, null);
        var classCtorInfo = typeof(TypeAttribute).
                   GetConstructor(new Type[] { typeof(Type) });

        Type tArg = typeof(float); // for no real reason
        var myCABuilder = new CustomAttributeBuilder(
            classCtorInfo, new object[] { tArg });
        propertyBuilder.SetCustomAttribute(myCABuilder);

        var field = tb.DefineField("myField", propertyType, FieldAttributes.Private);
        var getter = tb.DefineMethod("get_" + propertyName,
            MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Public,
            propertyType, Type.EmptyTypes);
        propertyBuilder.SetGetMethod(getter);
        var il = getter.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldfld, field);
        il.Emit(OpCodes.Ret);
        var setter = tb.DefineMethod("set_" + propertyName,
            MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Public,
            typeof(void), new[] { typeof(int) });
        il = setter.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Stfld, field);
        il.Emit(OpCodes.Ret);
        propertyBuilder.SetSetMethod(setter);
        var target = Activator.CreateInstance(tb.CreateType());        

        List<PropertyInfo> result = target.GetType()
          .GetProperties()
          .Where(
             p =>
                p.GetCustomAttributes(typeof(TypeAttribute), true)
                 //.Where(ca => ((TypeAttribute)ca).)
                .Any()
             ).ToList();
    }
}

此外,如果只关心它退出,使用 Attribute.IsDefined 会更有效.

Also, it is more efficient to use Attribute.IsDefined if you just care that it exits.

List<PropertyInfo> result = target.GetType().GetProperties()
      .Where(p => Attribute.IsDefined(p, typeof(TypeAttribute), true)).ToList();

还请注意,我不得不欺骗 getType(dataType)东西-我看不到它在做什么,因为它不是问题所在.确保它返回 Type .

Note also that I had to spoof the getType(dataType) stuff - I couldn't see what that was doing as it wasn't in the question. Make sure it returns a Type.

这篇关于从动态生成的类获取属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆