如何发现所有类,包括在运行时附加属性的子类?

时间:2013-12-03 18:23:52

标签: c# reflection static attributes static-constructor

我有一个属性用于标记解决方案中的某些类。我必须检查此属性是否在移动的对象上。这项检查(type.IsDefined(typeof(XmlImmutableAttribute), true);)正在经常进行,这正在成为负担并损害性能。我之前处理过类似的问题,找到附加了属性的所有类型并将它们存储在HashSet中,并检查set.Contains(type);(参见我的回答here)。这是我目前的代码:

public class XmlImmutableAttribute : XmlSerializedAttribute {

    private static readonly HashSet<Type> m_XmlImmutableAttributeTypes; // Set for the quick lookup of types that are marked with the XmlImmutableAttribute

    public XmlImmutableAttribute() {
    }

    static XmlImmutableAttribute() { // 
            m_XmlImmutableAttributeTypes = new HashSet<Type>();
            foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) {
                foreach (Type type in assembly.GetTypes()) {
                    if (type.IsDefined(typeof(XmlImmutableAttribute), false)) {
                        m_XmlImmutableAttributeTypes.Add(type);
                    }
                }
            }
    }

    public static bool IsAttachedTo(Type type) { // returns true if the attached type is marked immutable
        return m_XmlImmutableAttributeTypes.Contains(type);
    } 

    public static bool IsAttachedTo<T>() { // returns true if the attached type is marked immutable
        return IsAttachedTo(typeof(T));
    } 
}

问题是m_XmlImmutableAttributeTypes仅被初始化为包含具有直接附加属性的类型,而不包含已从附加类型中分类的类型。我假设这是在属性本身的静态构造函数中完成检查的问题,因为当我在静态初始化之后检查子类上的type.IsDefined(typeof(XmlImmutableAttribute), false)时,它返回true。如何保持这种预先确定类型的模式以提高效率,同时还要检测附加了属性的子类?

2 个答案:

答案 0 :(得分:1)

更改

if (type.IsDefined(typeof(XmlImmutableAttribute), false))

if (type.IsDefined(typeof(XmlImmutableAttribute), true))

在继承链中搜索

答案 1 :(得分:0)

我可能会重构你的属性以使用这样的延迟初始化:

public class XmlImmutableAttribute : XmlSerializedAttribute
{

  private static readonly object _syncroot       = new object() ;
  private static HashSet<Type>   _immutableTypes = null ; 
  private static HashSet<Type> ImmutableTypes
  {
    get
    {
      lock ( _syncroot )
      {
        if ( _immutableTypes == null )
        {
          _immutableTypes = new HashSet<Type>(
                              AppDomain
                              .CurrentDomain
                              .GetAssemblies()
                              .SelectMany( a => a.GetTypes() )
                              .Where( t => t.IsDefined( typeof(XmlImmutableAttribute) , true ) )
                              ) ;
        }
      }
      return _immutableTypes ;
    }
  }

  public static bool IsAttachedTo( Type type )
  {
    bool isImmutable = ImmutableTypes.Contains(type) ;
    return isImmutable ;
  }

  public static bool IsAttachedTo<T>()
  { // returns true if the attached type is marked immutable
    return IsAttachedTo( typeof( T ) );
  }

}

如果这不起作用,另一种方法是缓存查找,因此:

public class XmlImmutableAttribute : XmlSerializedAttribute
{

  private static readonly Dictionary<Type,bool> ImmutableTypes = new Dictionary<Type,bool>() ;

  public static bool IsAttachedTo( Type type )
  {
    if ( type == null ) throw new ArgumentNullException("type");
    bool isImmutable ;
    lock ( ImmutableTypes )
    {
      bool found = ImmutableTypes.TryGetValue(type, out isImmutable ) ;
      if ( !found )
      {
        isImmutable = type.IsDefined(typeof(XmlImmutableAttribute),true) ;
        ImmutableTypes.Add(type,isImmutable) ;
      }
    }
    return isImmutable ;
  }

  public static bool IsAttachedTo<T>()
  { // returns true if the attached type is marked immutable
    return IsAttachedTo( typeof(T) );
  }

}