
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(); }} 总结 以上是内存溢出为你收集整理的反射 – 如何优化此方法全部内容,希望文章能够帮你解决反射 – 如何优化此方法所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)