Question

I have an attribute that I use to mark certain classes in my solution. I have to check whether this attribute is on objects that are moving around. This check (type.IsDefined(typeof(XmlImmutableAttribute), true);) is being done so often that is is becoming a burden and hurting performance. I have dealt with a similar problem before by finding all the types with the attribute attached and storing them in a HashSet, and checking set.Contains(type); (see my answer here). This is the code I currently have:

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));
    } 
}

The issue is that m_XmlImmutableAttributeTypes only becomes initialized to contain the types that have the attributes directly attached, and non of the types that have been sub classed from the type attached. I assume this is an issue with the check being done in the static constructor of the attribute itself, because when I check type.IsDefined(typeof(XmlImmutableAttribute), false) on a subclass after the static initialization, it returns true. How can I maintain this pattern of predetermining types for increased efficiency, while also having it detect the sub classes with the attribute attached?

Was it helpful?

Solution

Change

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

to

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

to search in the inheritance chain

OTHER TIPS

I'd probably refactor your attribute to use lazy initialization like this:

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 ) );
  }

}

If that doesn't work, another approach would be to do cache the lookups, thus:

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) );
  }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top