反射 – 如何优化此方法
发布时间:2020-12-16 09:28:44 所属栏目:百科 来源:网络整理
导读:private static void ConvertToUpper(object entity,Hashtable visited) { if (entity != null !visited.ContainsKey(entity)) { visited.Add(entity,entity); foreach (PropertyInfo propertyInfo in entity.GetType().GetProperties()) { if (!propertyInf
private static void ConvertToUpper(object entity,Hashtable visited) { if (entity != null && !visited.ContainsKey(entity)) { visited.Add(entity,entity); foreach (PropertyInfo propertyInfo in entity.GetType().GetProperties()) { if (!propertyInfo.CanRead || !propertyInfo.CanWrite) continue; object propertyValue = propertyInfo.GetValue(entity,null); Type propertyType; if ((propertyType = propertyInfo.PropertyType) == typeof(string)) { if (propertyValue != null && !propertyInfo.Name.Contains("password")) { propertyInfo.SetValue(entity,((string)propertyValue).ToUpper(),null); } continue; } if (!propertyType.IsValueType) { IEnumerable enumerable; if ((enumerable = propertyValue as IEnumerable) != null) { foreach (object value in enumerable) { ConvertToUpper(value,visited); } } else { ConvertToUpper(propertyValue,visited); } } } } } 现在它适用于列表相对较小的对象,但是一旦对象列表变大,就需要永远.我将如何优化它并设置最大深度的限制. 谢谢你的帮助 解决方法
我没有描述下面的代码,但它必须在复杂的结构上非常高效.
1)使用动态代码生成. 2)为生成的动态委托使用基于类型的缓存. public class VisitorManager : HashSet<object> { delegate void Visitor(VisitorManager manager,object entity); Dictionary<Type,Visitor> _visitors = new Dictionary<Type,Visitor>(); void ConvertToUpperEnum(IEnumerable entity) { // TODO: this can be parallelized,but then we should thread-safe lock the cache foreach (var obj in entity) ConvertToUpper(obj); } public void ConvertToUpper(object entity) { if (entity != null && !Contains(entity)) { Add(entity); var visitor = GetCachedVisitor(entity.GetType()); if (visitor != null) visitor(this,entity); } } Type _lastType; Visitor _lastVisitor; Visitor GetCachedVisitor(Type type) { if (type == _lastType) return _lastVisitor; _lastType = type; return _lastVisitor = GetVisitor(type); } Visitor GetVisitor(Type type) { Visitor result; if (!_visitors.TryGetValue(type,out result)) _visitors[type] = result = BuildVisitor(type); return result; } static MethodInfo _toUpper = typeof(string).GetMethod("ToUpper",new Type[0]); static MethodInfo _convertToUpper = typeof(VisitorManager).GetMethod("ConvertToUpper",BindingFlags.Instance | BindingFlags.Public); static MethodInfo _convertToUpperEnum = typeof(VisitorManager).GetMethod("ConvertToUpperEnum",BindingFlags.Instance | BindingFlags.NonPublic); Visitor BuildVisitor(Type type) { var visitorManager = Expression.Parameter(typeof(VisitorManager),"manager"); var entityParam = Expression.Parameter(typeof(object),"entity"); var entityVar = Expression.Variable(type,"e"); var cast = Expression.Assign(entityVar,Expression.Convert(entityParam,type)); // T e = (T)entity; var statements = new List<Expression>() { cast }; foreach (var prop in type.GetProperties()) { // if cannot read or cannot write - ignore property if (!prop.CanRead || !prop.CanWrite) continue; var propType = prop.PropertyType; // if property is value type - ignore property if (propType.IsValueType) continue; var isString = propType == typeof(string); // if string type but no password in property name - ignore property if (isString && !prop.Name.Contains("password")) continue; #region e.Prop var propAccess = Expression.Property(entityVar,prop); // e.Prop #endregion #region T value = e.Prop var value = Expression.Variable(propType,"value"); var assignValue = Expression.Assign(value,propAccess); #endregion if (isString) { #region if (value != null) e.Prop = value.ToUpper(); var ifThen = Expression.IfThen(Expression.NotEqual(value,Expression.Constant(null,typeof(string))),Expression.Assign(propAccess,Expression.Call(value,_toUpper))); #endregion statements.Add(Expression.Block(new[] { value },assignValue,ifThen)); } else { #region var i = value as IEnumerable; var enumerable = Expression.Variable(typeof(IEnumerable),"i"); var assignEnum = Expression.Assign(enumerable,Expression.TypeAs(value,enumerable.Type)); #endregion #region if (i != null) manager.ConvertToUpperEnum(i); else manager.ConvertToUpper(value); var ifThenElse = Expression.IfThenElse(Expression.NotEqual(enumerable,Expression.Constant(null)),Expression.Call(visitorManager,_convertToUpperEnum,enumerable),_convertToUpper,value)); #endregion statements.Add(Expression.Block(new[] { value,enumerable },assignEnum,ifThenElse)); } } // no blocks if (statements.Count <= 1) return null; return Expression.Lambda<Visitor>(Expression.Block(new[] { entityVar },statements),visitorManager,entityParam).Compile(); } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |