反射 – 如何优化此方法

反射 – 如何优化此方法,第1张

概述private static void ConvertToUpper(object entity, Hashtable visited) { if (entity != null && !visited.ContainsKey(entity)) { visited.Add(entity, entity); f
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();  }}
总结

以上是内存溢出为你收集整理的反射 – 如何优化此方法全部内容,希望文章能够帮你解决反射 – 如何优化此方法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1212958.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-04
下一篇2022-06-04

发表评论

登录后才能评论

评论列表(0条)

    保存