反射性能 - 使用条件参数创建委托(属性 C#)
Reflection Performance - Create Delegate (Properties C#) With Conditional Parameters
我正在使用问题的解决方案:Reflection Performance - Create Delegate (Properties C#)
我有以下代码:
private static Action<object, object> BuildSetAccessor(string name, MethodInfo method)
{
if (method == null) return null;
if (method.DeclaringType == null) return null;
var obj = Expression.Parameter(typeof(object), name);
var value = Expression.Parameter(typeof(object));
var expr = Expression.Lambda<Action<object, object>>(Expression.Call(Expression.Convert(obj, method.DeclaringType), method, Expression.Convert(value, method.GetParameters()[0].ParameterType)), obj, value);
return expr.Compile();
}
private static Func<object, object> BuildGetAccessor(string name, MethodInfo method)
{
if (method.DeclaringType == null) return null;
var obj = Expression.Parameter(typeof(object), name);
var expr = Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Call(Expression.Convert(obj, method.DeclaringType), method), typeof(object)), obj);
return expr.Compile();
}
正在使用代码...
var cacheProperty = new CacheForReflectionClassProperty()
{
Name = p.Name,
SetValue = BuildSetAccessor(p.Name, p.GetSetMethod()),
GetValue = BuildGetAccessor(p.Name, p.GetGetMethod())
};
if (Attribute.IsDefined(p, typeof(IsIdentityColumn)))
{
// TODO: Instead of just getting the old value,
// I need to verify if the value is NULL
// in that case I need to create a new value of ID type....
// and at the end I need to use the SetValue() method as well
GetValue = .... // TODO:
}
else if (Attribute.IsDefined(p, typeof(IsCreatedOnColumn)))
{
// TODO: Instead of just getting the old value,
// I need to verify if the value is NULL
// in that case I need to create a new value with DateTime.UtcNow
// and at the end I need to use the SetValue() method as well
GetValue = .... // TODO:
}
我知道我需要创建以下方法:
private static Func<object, object> BuildGetAccessorForIdentityColumn(string name, MethodInfo method)
private static Func<object, object> BuildGetAccessorForCreatedOnColumn(string name, MethodInfo method)
我已经尝试学习如何使用表达式树,但我还没有找到一种方法,让我的 BuildGetAccessor 不仅可以获取值,还可以将结果与某些东西进行比较,如果需要,还需要使用 BuildSetAccessor。
我该怎么做?
你这样做是因为反射会影响性能。但是在你完成反射部分之后 - 你不需要再使用编译表达式 - 只需使用常规代码:
var getAccessor = BuildGetAccessor(p.Name, p.GetGetMethod());
var setAccessor = BuildSetAccessor(p.Name, p.GetSetMethod());
// if IsCreatedOnColumn
cacheProperty.GetValue = (instance) =>
{
var value = getAccessor(instance);
if (value == null)
{
value = DateTime.UtcNow;
setAccessor(instance, value);
}
return value;
};
我正在使用问题的解决方案:Reflection Performance - Create Delegate (Properties C#)
我有以下代码:
private static Action<object, object> BuildSetAccessor(string name, MethodInfo method)
{
if (method == null) return null;
if (method.DeclaringType == null) return null;
var obj = Expression.Parameter(typeof(object), name);
var value = Expression.Parameter(typeof(object));
var expr = Expression.Lambda<Action<object, object>>(Expression.Call(Expression.Convert(obj, method.DeclaringType), method, Expression.Convert(value, method.GetParameters()[0].ParameterType)), obj, value);
return expr.Compile();
}
private static Func<object, object> BuildGetAccessor(string name, MethodInfo method)
{
if (method.DeclaringType == null) return null;
var obj = Expression.Parameter(typeof(object), name);
var expr = Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Call(Expression.Convert(obj, method.DeclaringType), method), typeof(object)), obj);
return expr.Compile();
}
正在使用代码...
var cacheProperty = new CacheForReflectionClassProperty()
{
Name = p.Name,
SetValue = BuildSetAccessor(p.Name, p.GetSetMethod()),
GetValue = BuildGetAccessor(p.Name, p.GetGetMethod())
};
if (Attribute.IsDefined(p, typeof(IsIdentityColumn)))
{
// TODO: Instead of just getting the old value,
// I need to verify if the value is NULL
// in that case I need to create a new value of ID type....
// and at the end I need to use the SetValue() method as well
GetValue = .... // TODO:
}
else if (Attribute.IsDefined(p, typeof(IsCreatedOnColumn)))
{
// TODO: Instead of just getting the old value,
// I need to verify if the value is NULL
// in that case I need to create a new value with DateTime.UtcNow
// and at the end I need to use the SetValue() method as well
GetValue = .... // TODO:
}
我知道我需要创建以下方法:
private static Func<object, object> BuildGetAccessorForIdentityColumn(string name, MethodInfo method)
private static Func<object, object> BuildGetAccessorForCreatedOnColumn(string name, MethodInfo method)
我已经尝试学习如何使用表达式树,但我还没有找到一种方法,让我的 BuildGetAccessor 不仅可以获取值,还可以将结果与某些东西进行比较,如果需要,还需要使用 BuildSetAccessor。
我该怎么做?
你这样做是因为反射会影响性能。但是在你完成反射部分之后 - 你不需要再使用编译表达式 - 只需使用常规代码:
var getAccessor = BuildGetAccessor(p.Name, p.GetGetMethod());
var setAccessor = BuildSetAccessor(p.Name, p.GetSetMethod());
// if IsCreatedOnColumn
cacheProperty.GetValue = (instance) =>
{
var value = getAccessor(instance);
if (value == null)
{
value = DateTime.UtcNow;
setAccessor(instance, value);
}
return value;
};