him again! :)
I was instructed to create a system for checking internal objects, my first iteration was not flexible and very slow, so I hope to rewrite it and really make it work as it should.
The performance for this should be as perfect as possible, the verification code is likely to be run on each object of our system when they are saved.
This code below is what I have done so far. I have profiled it using visual studio tools, and I think that I am removing quite a few possible performance hits along the way.
What I really want from you guys is to look over this and suggest any possible improvements. It also does not cost anything that the CreateObjectFromHistory method does not have to be as efficient as the rest, it can hardly ever be called.
In addition, they retain a shortage of keys.
Any help would be brilliant.
Greetings :)
// Wall-mounted o-code.
public static void AuditObject(ITraceable obj) { if (obj == null) return; IEnumerable<PropertyInfo> properties = GetPropertyInfo(obj); List<SerializeableKeyValuePair<string, object>> kvpList = new List<SerializeableKeyValuePair<string, object>>(); foreach (PropertyInfo property in properties) { SerializeableKeyValuePair<string, object> thisValue = new SerializeableKeyValuePair<string, object>(); thisValue.Key = property.Name; thisValue.Value = GetPropertyValue(obj, property); if (thisValue.Value != null) kvpList.Add(thisValue); } TestObject o = CreateObjectFromHistory<TestObject>(kvpList); } public static T CreateObjectFromHistory<T>(List<SerializeableKeyValuePair<string, object>> history) where T : class, ITraceable { T historicalObject = Activator.CreateInstance<T>(); Dictionary<string, PropertyInfo> propertys = GetPropertysAsDictionary(historicalObject); foreach (SerializeableKeyValuePair<string, object> kvp in history) { if (!propertys.ContainsKey(kvp.Key)) continue; PropertyInfo prop = propertys[kvp.Key]; if (prop == null) continue; var value = CoerceValue(prop.PropertyType, kvp.Value); prop.SetValue(historicalObject, value, null); } return historicalObject; } private static object CoerceValue(Type type, object value) { if (type == typeof(string)) return value as string; return null; } private static object GetPropertyValue(ITraceable obj, PropertyInfo property) { if (property.PropertyType == typeof(string)) return GetProperyValueByType<string>(property.GetValue(obj, null)); else if (property.PropertyType == typeof(DateTime)) return GetProperyValueByType<DateTime>(property.GetValue(obj, null)); return null; } private static IEnumerable<PropertyInfo> GetPropertyInfo(ITraceable obj) { List<PropertyInfo> properties; Type objType = obj.GetType(); if (PropertyDictionary.TryGetValue(objType, out properties) == false) { properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList(); properties.RemoveAll(p => IgnoreProperty(p.GetCustomAttributes(typeof(DoNoTraceAttribute), false))); PropertyDictionary.Add(objType, properties); } return properties; } private static Dictionary<string, PropertyInfo> GetPropertysAsDictionary(ITraceable obj) { return GetPropertyInfo(obj).ToDictionary(pro => pro.Name); } private static object GetProperyValueByType<T>(object value) { T actualType = (T)value; if (actualType.Equals(default(T))) return default(T);
Updated code
private static IEnumerable<PropertyInfo> GetPropertyInfo(ITraceable obj) { List<PropertyInfo> properties; Type objType = obj.GetType(); if (PropertyDictionary.TryGetValue(objType, out properties) == false) { properties = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList(); properties.RemoveAll(p => Attribute.IsDefined(p, typeof(DoNoTraceAttribute))); PropertyDictionary.Add(objType, properties); } return properties; }
Do it better?