Audit an object using reflection

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); //this will need further implementation return (T)value; } private static bool IgnoreProperty(IEnumerable<object> p) { return p.AsParallel().OfType<DoNoTraceAttribute>().Any(); } 

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?

+4
source share
1 answer

If you use PropertyInfo.GetValue() at runtime, performance will always be slow. To get good performance (especially for viewing a lot of objects), you need to look at something like ILGenerator or Expression - or you could just use something like FastMember and access the values โ€‹โ€‹through prop.Name . I really don't think IgnoreProperty implemented well - you should just look at Attribute.IsDefined here; there is no need for LINQ, no need for Parallel , and no need to materialize attributes.

+3
source

Source: https://habr.com/ru/post/1394356/


All Articles