C# 为属性设置程序或获取程序创建performant open委托
开放委托是对没有目标的实例方法的委托。要调用它,请提供目标作为其第一个参数。它们是优化代码的一种聪明方法,否则会使用反射,性能会很差。有关打开学员的介绍,请参见。在实践中使用它的方法是使用昂贵的反射代码来构建这些开放委托,但这样就可以以非常便宜的方式调用它们,只需简单的委托调用 我正在尝试编写代码,将任意属性信息转换为其setter的委托。到目前为止,我得出了以下结论:C# 为属性设置程序或获取程序创建performant open委托,c#,reflection,delegates,C#,Reflection,Delegates,开放委托是对没有目标的实例方法的委托。要调用它,请提供目标作为其第一个参数。它们是优化代码的一种聪明方法,否则会使用反射,性能会很差。有关打开学员的介绍,请参见。在实践中使用它的方法是使用昂贵的反射代码来构建这些开放委托,但这样就可以以非常便宜的方式调用它们,只需简单的委托调用 我正在尝试编写代码,将任意属性信息转换为其setter的委托。到目前为止,我得出了以下结论: using System; using System.Collections.Generic; using System.Li
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Test
{
class TestClass
{
static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
{
MethodInfo setMethod = property.GetSetMethod();
if (setMethod != null && setMethod.GetParameters().Length == 1) //skips over nasty index properties
{
//To be able to bind to the delegate we have to create a delegate
//type like: Action<T,actualType> rather than Action<T,object>.
//We use reflection to do that
Type setterGenericType = typeof(Action<,>);
Type delegateType = setterGenericType.MakeGenericType(new Type[] { typeof(T), property.PropertyType });
var untypedDelegate = Delegate.CreateDelegate(delegateType, setMethod);
//we wrap the Action<T,actualType> delegate into an Action<T,object>
Action<T, object> setter = (instance, value) =>
{
untypedDelegate.DynamicInvoke(new object[] { instance, value });
};
return setter;
}
else
{
return null;
}
}
int TestProp
{
set
{
System.Diagnostics.Debug.WriteLine("Called set_TestProp");
}
}
static void Test()
{
PropertyInfo property = typeof(TestClass).GetProperty("TestProp");
Action<TestClass, object> setter = MakeSetterDelegate<TestClass>(property);
TestClass instance = new TestClass();
setter(instance, 5);
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
运用系统反思;
名称空间测试
{
类TestClass
{
静态操作MakeSetterLegate(PropertyInfo属性)
{
MethodInfo setMethod=property.GetSetMethod();
if(setMethod!=null&&setMethod.GetParameters().Length==1)//跳过索引属性
{
//为了能够绑定到委托,我们必须创建一个委托
//类型:Action而不是Action。
//我们使用反射来实现这一点
类型setterGenericType=typeof(动作);
类型delegateType=setterGenericType.MakeGenericType(新类型[]{typeof(T),property.PropertyType});
var untypedDelegate=Delegate.CreateDelegate(delegateType,setMethod);
//我们将动作委托包装成一个动作
动作设置器=(实例,值)=>
{
DynamicInvoke(新对象[]{instance,value});
};
回程设定器;
}
其他的
{
返回null;
}
}
int TestProp
{
设置
{
System.Diagnostics.Debug.WriteLine(“称为set_TestProp”);
}
}
静态孔隙试验()
{
PropertyInfo property=typeof(TestClass).GetProperty(“TestProp”);
Action setter=MakeSetterDelegate(属性);
TestClass实例=新的TestClass();
setter(实例5);
}
}
}
将为getter编写类似的代码。这是可行的,但setter委托使用DynamicInvoke将动作转换为动作,我怀疑这会侵蚀我所追求的优化的很大一部分。因此,问题是:
DynamicVoke真的令人担忧吗
它周围有什么东西吗
DynamicInvoke
不会成为性能设置器。在这里,针对泛型内部类型的反射是更好的选择,因为这将允许您使用类型化委托。另一个选项是DynamicMethod
,但是您需要担心一些细节
您可能想看看HyperDescriptor
,它将IL工作封装到PropertyDescriptor
实现中。另一个选项是表达式
API(如果您使用的是.NET 3.5或更高版本):
静态操作MakeSetterLegate(PropertyInfo属性)
{
MethodInfo setMethod=property.GetSetMethod();
if(setMethod!=null&&setMethod.GetParameters().Length==1)
{
var target=Expression.Parameter(typeof(T));
var值=表达式参数(typeof(object));
var body=Expression.Call(target,setMethod,
Convert(value,property.PropertyType));
返回表达式.Lambda(主体、目标、值)
.Compile();
}
其他的
{
返回null;
}
}
或者使用泛型类型:
abstract class Setter<T>
{
public abstract void Set(T obj, object value);
}
class Setter<TTarget, TValue> : Setter<TTarget>
{
private readonly Action<TTarget, TValue> del;
public Setter(MethodInfo method)
{
del = (Action<TTarget, TValue>)
Delegate.CreateDelegate(typeof(Action<TTarget, TValue>), method);
}
public override void Set(TTarget obj, object value)
{
del(obj, (TValue)value);
}
}
static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
{
MethodInfo setMethod = property.GetSetMethod();
if (setMethod != null && setMethod.GetParameters().Length == 1)
{
Setter<T> untyped = (Setter<T>) Activator.CreateInstance(
typeof(Setter<,>).MakeGenericType(typeof(T),
property.PropertyType), setMethod);
return untyped.Set;
}
else
{
return null;
}
}
抽象类设置器
{
公共抽象空集(T obj,对象值);
}
类设置器:设置器
{
私有只读操作;
公共设置器(MethodInfo方法)
{
del=(动作)
CreateDelegate(typeof(Action),method);
}
公共替代无效集(目标对象,对象值)
{
del(obj,(TValue)值);
}
}
静态操作MakeSetterLegate(PropertyInfo属性)
{
MethodInfo setMethod=property.GetSetMethod();
if(setMethod!=null&&setMethod.GetParameters().Length==1)
{
Setter untyped=(Setter)Activator.CreateInstance(
排版机,
property.PropertyType),setMethod);
返回非类型化的.Set;
}
其他的
{
返回null;
}
}
我曾经上过这门课。也许这有助于:
public class GetterSetter<EntityType,propType>
{
private readonly Func<EntityType, propType> getter;
private readonly Action<EntityType, propType> setter;
private readonly string propertyName;
private readonly Expression<Func<EntityType, propType>> propertyNameExpression;
public EntityType Entity { get; set; }
public GetterSetter(EntityType entity, Expression<Func<EntityType, propType>> property_NameExpression)
{
Entity = entity;
propertyName = GetPropertyName(property_NameExpression);
propertyNameExpression = property_NameExpression;
//Create Getter
getter = propertyNameExpression.Compile();
// Create Setter()
MethodInfo method = typeof (EntityType).GetProperty(propertyName).GetSetMethod();
setter = (Action<EntityType, propType>)
Delegate.CreateDelegate(typeof(Action<EntityType, propType>), method);
}
public propType Value
{
get
{
return getter(Entity);
}
set
{
setter(Entity, value);
}
}
protected string GetPropertyName(LambdaExpression _propertyNameExpression)
{
var lambda = _propertyNameExpression as LambdaExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = lambda.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
var propertyInfo = memberExpression.Member as PropertyInfo;
return propertyInfo.Name;
}
公共类GetterSetter
{
私有只读函数getter;
私有只读操作设置器;
私有只读字符串propertyName;
私有只读表达式propertyNameExpression;
公共EntityType实体{get;set;}
公共GetterSetter(EntityType实体、表达式属性\u NameExpression)
{
实体=实体;
propertyName=GetPropertyName(属性\名称表达式);
propertyNameExpression=属性\名称表达式;
//创建Getter
getter=propertyNameExpression.Compile();
//创建Setter()
MethodInfo method=typeof(EntityType).GetProperty(propertyName).GetSetMethod();
setter=(操作)
CreateDelegate(typeof(Action),method);
}
公共propType值
{
得到
{
返回getter(实体);
}
设置
{
setter(实体、值);
}
}
受保护的字符串GetPropertyName(LambdaExpression\u propertyNameExpression)
{
var lambda=_propertyNameExpression作为LambdaExpression;
成员表达成员表达;
if(lambda.Body是一元表达式)
{
变量一元表达式
public class GetterSetter<EntityType,propType>
{
private readonly Func<EntityType, propType> getter;
private readonly Action<EntityType, propType> setter;
private readonly string propertyName;
private readonly Expression<Func<EntityType, propType>> propertyNameExpression;
public EntityType Entity { get; set; }
public GetterSetter(EntityType entity, Expression<Func<EntityType, propType>> property_NameExpression)
{
Entity = entity;
propertyName = GetPropertyName(property_NameExpression);
propertyNameExpression = property_NameExpression;
//Create Getter
getter = propertyNameExpression.Compile();
// Create Setter()
MethodInfo method = typeof (EntityType).GetProperty(propertyName).GetSetMethod();
setter = (Action<EntityType, propType>)
Delegate.CreateDelegate(typeof(Action<EntityType, propType>), method);
}
public propType Value
{
get
{
return getter(Entity);
}
set
{
setter(Entity, value);
}
}
protected string GetPropertyName(LambdaExpression _propertyNameExpression)
{
var lambda = _propertyNameExpression as LambdaExpression;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = lambda.Body as UnaryExpression;
memberExpression = unaryExpression.Operand as MemberExpression;
}
else
{
memberExpression = lambda.Body as MemberExpression;
}
var propertyInfo = memberExpression.Member as PropertyInfo;
return propertyInfo.Name;
}
var gs = new GetterSetter<OnOffElement,bool>(new OnOffElement(), item => item.IsOn);
gs.Value = true;
var result = gs.Value;