C# 为属性设置程序或获取程序创建performant open委托

C# 为属性设置程序或获取程序创建performant open委托,c#,reflection,delegates,C#,Reflection,Delegates,开放委托是对没有目标的实例方法的委托。要调用它,请提供目标作为其第一个参数。它们是优化代码的一种聪明方法,否则会使用反射,性能会很差。有关打开学员的介绍,请参见。在实践中使用它的方法是使用昂贵的反射代码来构建这些开放委托,但这样就可以以非常便宜的方式调用它们,只需简单的委托调用 我正在尝试编写代码,将任意属性信息转换为其setter的委托。到目前为止,我得出了以下结论: using System; using System.Collections.Generic; using System.Li

开放委托是对没有目标的实例方法的委托。要调用它,请提供目标作为其第一个参数。它们是优化代码的一种聪明方法,否则会使用反射,性能会很差。有关打开学员的介绍,请参见。在实践中使用它的方法是使用昂贵的反射代码来构建这些开放委托,但这样就可以以非常便宜的方式调用它们,只需简单的委托调用

我正在尝试编写代码,将任意属性信息转换为其setter的委托。到目前为止,我得出了以下结论:

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;