gpt4 book ai didi

reflection - 如何优化此方法

转载 作者:行者123 更新时间:2023-12-01 10:13:40 25 4
gpt4 key购买 nike

 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) 对生成的动态委托(delegate)使用基于类型的缓存。

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),
Expression.Call(visitorManager, _convertToUpper, value));

#endregion

statements.Add(Expression.Block(new[] { value, enumerable }, assignValue, assignEnum, ifThenElse));
}
}

// no blocks
if (statements.Count <= 1)
return null;

return Expression.Lambda<Visitor>(Expression.Block(new[] { entityVar }, statements), visitorManager, entityParam).Compile();
}
}

关于reflection - 如何优化此方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3214613/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com