Visual C# Developer Center > Visual C# Forums > Visual C# General > Best practices: Implementing static class initializer across many classes?
Ask a questionAsk a question
 

AnswerBest practices: Implementing static class initializer across many classes?

  • Tuesday, November 03, 2009 3:13 PMdbooksta Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    I am using [Data] attributes to tag some properties for frequent reference in many classes.

    In order to access their values in a reasonable amount of time I implement a static constructor in every class that might contain [Data] properties to enumerate via reflection only those properties, as follows:

            static Dictionary<PropertyInfo, DataAttribute> sData;
            static MyClass()
            {
                // Build list of properties we will database
                sData = new Dictionary<PropertyInfo, DataAttribute>();            
                foreach (PropertyInfo p in typeof(MyClass).GetProperties(BindingFlags.Public | BindingFlags.Instance))
                {
                    object[] o = p.GetCustomAttributes(typeof(DataAttribute), true);
                    if (o.Length > 0)
                        sData.Add(p, (DataAttribute)o[0]);
                }
            }
    
    This way when I frequently come to get them I can iterate only over the properties I know have the Data attribute I want to reflect.  E.g.,

            public List<Data> GetData()
            {
                List<Data> r = new List<Data>();
                foreach (KeyValuePair<PropertyInfo, DataAttribute> kvp in sData)
                {
                    r.Add(new Data(myName, kvp.Value, Convert.ToDouble(kvp.Key.GetValue(this, null))));
                }
            }
    

    But it seems wrong to copy this static class initializer into every class.  Is there a design pattern or paradigm to keep the logic for caching [Data] properties in a single place?  Or any better way of implementing this?

Answers

  • Tuesday, November 03, 2009 4:22 PMNicole Calinoiu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    For starters, you should avoid writing explicit static constructors where at all possible (http://msdn.microsoft.com/en-us/library/ms182275.aspx).

    In this case, you should perhaps consider using a custom class instead of a Dictionary<,>.  This class could accept the target type as an instance constructor parameter, and the logic for reading the data properties from the target type could be moved to that instance constructor.
    • Marked As Answer bydbooksta Tuesday, November 03, 2009 7:14 PM
    •  

All Replies

  • Tuesday, November 03, 2009 4:22 PMNicole Calinoiu Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    For starters, you should avoid writing explicit static constructors where at all possible (http://msdn.microsoft.com/en-us/library/ms182275.aspx).

    In this case, you should perhaps consider using a custom class instead of a Dictionary<,>.  This class could accept the target type as an instance constructor parameter, and the logic for reading the data properties from the target type could be moved to that instance constructor.
    • Marked As Answer bydbooksta Tuesday, November 03, 2009 7:14 PM
    •  
  • Tuesday, November 03, 2009 4:28 PMRudedog2ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    You need an Abstract Object Factory.  What is known as a Design Pattern .

    Abstract Factory

    Factory Method


    Mark the best replies as answers. "Fooling computers since 1971."
  • Tuesday, November 03, 2009 7:14 PMdbooksta Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    Thanks.  Putting this into a static class worked quite well:

            public static List<Data> GetData(object o, string group, string name)
            {
                List<Data> r = new List<Data>();
                foreach (KeyValuePair<PropertyInfo, DataAttribute> kvp in GetIntradayDataProperties(o.GetType()))
                {
                    kvp.Value.Group = group;
                    r.Add(new Data(name, kvp.Value, Convert.ToDouble(kvp.Key.GetValue(o, null))));
                }
                return r;
            }
    
            // Cache of DataAttribute properties for each Type
            static Dictionary<Type, Dictionary<PropertyInfo, DataAttribute>> sDataReflection = new Dictionary<Type, Dictionary<PropertyInfo,DataAttribute>>();
    
            public static Dictionary<PropertyInfo, DataAttribute> GetDataProperties(Type t)
            {
                Dictionary<PropertyInfo, DataAttribute> properties;
                // Get cached value if available
                if(sDataReflection.TryGetValue(t, out properties))
                    return properties;
                // Otherwise compute and dictionary before returning
                properties = new Dictionary<PropertyInfo, DataAttribute>();
                foreach (PropertyInfo p in t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                {
                    object[] o = p.GetCustomAttributes(typeof(DataAttribute), true);
                    if (o.Length > 0)
                        properties.Add(p, (DataAttribute)o[0]);
                }
                sDataReflection[t] = properties;
                return properties;
            }