Visual C# Developer Center >
Visual C# Forums
>
Visual C# General
>
Best practices: Implementing static class initializer across many classes?
Best practices: Implementing static class initializer across many classes?
- 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
- 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
- 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
- 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." - 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; }


