在c#中按名称获取和保持属性引用的最佳方法是什么?

Jef*_*ber 2 c# reflection dynamic .net-4.0

我想知道是否有更好的方法(比我目前正在做的)只使用对象和属性字符串名来获取并保持对另一个对象中的属性的引用.特别是,使用.Net 4.0的新动态功能有更好的方法吗?

这就是我现在所拥有的.

我有一个" PropertyReference<T>"对象,它在构造函数中获取对象名称和属性名称.

一种Initialize()方法使用反射来找到对象和属性并且存储属性getter作为Action<T>和属性setter作为Func<T>.

当我想要实际调用属性时,我会做这样的事情:

int x = _propertyReference.Get();
Run Code Online (Sandbox Code Playgroud)

要么

_propertyReference.Set(2);
Run Code Online (Sandbox Code Playgroud)

这是我的PropertyReference<T>代码.请剖析并提出改进建议.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Xml;

namespace WindowsFormsApplication2
{
    public class PropertyReference<T> : IPropertyReference
    {
        public string ComponentName { get; set; }
        public string PropertyName { get; set; }
        public bool IsInitialized
        {
            get
            {
                return (_action != null && _func != null);
            }
        }

        Action<T> _action;
        Func<T> _func;

        public PropertyReference() { }

        public PropertyReference(string componentName, string propertyName)
        {
            ComponentName = componentName;
            PropertyName = propertyName;
        }

        public void Initialize(IEntity e)
        {            
            Object component = e.GetByName(ComponentName);
            if (component == null) return;

            Type t = e.GetByName(ComponentName).GetType();
            PropertyInfo pi = t.GetProperty(PropertyName);

            _action = (T a) => pi.SetValue(component, a, null);
            _func = () => (T)pi.GetValue(component, null);
        }

        public void Reset()
        {
            _action = null;
            _func = null;

        }

        public void Set(T value)
        {
            _action.Invoke(value);
        }

        public T Get()
        {
            return _func();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

注意:我无法使用"发射"功能,因为我需要此代码才能在新的Windows Phone 7上运行并且不支持Emit.

更新:

更换后刚做了一些速度测试:

_action = (T a) => pi.SetValue(component, a, null);
_func = () => (T)pi.GetValue(component, null);
Run Code Online (Sandbox Code Playgroud)

_action = Action<T>)Delegate.CreateDelegate(typeof(Action<T>),component,pi.GetSetMethod());
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
Run Code Online (Sandbox Code Playgroud)

正如下面的dtb所示.

通过对Get()属性进行100,000次调用来测试.结果如下.

_func = () => (T)pi.GetValue(component, null)
Run Code Online (Sandbox Code Playgroud)

花了大约200ms

_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
Run Code Online (Sandbox Code Playgroud)

花了大约10ms

巨大的差异.没想到,但很酷!

仍有更多改进.

dtb*_*dtb 5

您可以获得直接表示getter和setter方法的委托:

object component;
PropertyInfo pi;

_action = (Action<T>)Delegate.CreateDelegate(typeof(Action<T>),
                                             component,
                                             pi.GetSetMethod());

_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>),
                                         component,
                                         pi.GetGetMethod());
Run Code Online (Sandbox Code Playgroud)