我的任务是创建一个审计内部对象的系统,我的第一次迭代不灵活且非常慢,所以我希望能够重写它并真正使它工作的方式。
这需要尽可能完美,审计代码可能会在保存时在系统中的每个对象上运行。
下面的代码是我到目前为止所做的 - 我使用visual studio工具对其进行了分析,我认为我已经删除了一些可能的性能点击..
我真正想要的是审查这个并提出任何可能的改进建议, CreateObjectFromHistory 方法不需要像其他方法一样高效,它几乎不会永远都会被召唤。
另外 - 他们的keyvaluepair保存不在我手中。
任何帮助都会很棒......
干杯:)
//墙上的o代码即将出现..
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();
}
更新的代码;
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;
}
这看起来更好吗?
答案 0 :(得分:3)
如果在运行时使用PropertyInfo.GetValue()
,性能将始终很慢。要获得良好的性能(尤其是查看大量对象),您需要查看ILGenerator
或Expression
之类的内容 - 或者您可以使用FastMember之类的内容并通过prop.Name
。我真的认为IgnoreProperty
没有得到很好的实施 - 你应该在这里查看Attribute.IsDefined
;不需要LINQ,不需要Parallel
,也不需要实现属性。