[英]What is the best way get and hold property reference by name in c#
I want to know if there is a better way (than what I'm currently doing) to obtain and hold a reference to a property in another object using only the object and property string names. 我想知道是否有更好的方法(比我目前正在做的更好)来获取和持有仅使用对象和属性字符串名称的另一个对象中对属性的引用。 Particularly, is there a better way to do this with the new dynamic functionality of .Net 4.0?
尤其是,是否有更好的方法利用.Net 4.0的新动态功能来做到这一点?
Here is what I have right now. 这就是我现在所拥有的。
I have a " PropertyReference<T>
" object that takes an object name and property name in the constructor. 我有一个“
PropertyReference<T>
”对象,该对象在构造函数中带有对象名称和属性名称。
An Initialize()
method uses reflection to find the object and property and stores the property Getter as an Action<T>
and the property Setter as an Func<T>
. Initialize()
方法使用反射来查找对象和属性,并将Getter属性存储为Action<T>
而将Setter属性存储为Func<T>
。
When I want to actually call the property I do something like this: 当我想实际调用该属性时,请执行以下操作:
int x = _propertyReference.Get();
or 要么
_propertyReference.Set(2);
Here is my PropertyReference<T>
code. 这是我的
PropertyReference<T>
代码。 Please dissect and make suggestions for improvement. 请剖析并提出改进建议。
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();
}
}
}
Note: I can't use the "Emit" functionality as I need this code to work on the new Windows Phone 7 and that does not support Emit. 注意:我不能使用“发射”功能,因为我需要此代码在新的Windows Phone 7上工作,并且不支持发射。
UPDATE: 更新:
Just did some speed tests after replacing: 更换后只是做了一些速度测试:
_action = (T a) => pi.SetValue(component, a, null);
_func = () => (T)pi.GetValue(component, null);
With 同
_action = Action<T>)Delegate.CreateDelegate(typeof(Action<T>),component,pi.GetSetMethod());
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
As suggested by dtb below. 如以下dtb所建议。
Tested by making 100,000 calls to the Get() property. 通过对Get()属性进行100,000次调用进行了测试。 Here are the results.
这是结果。
_func = () => (T)pi.GetValue(component, null)
took about 200ms 花了大约200ms
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
took about 10ms 花了大约10ms
Huge difference. 差异很大。 Wasn't expecting that, but cool!
没想到,但是很酷!
Still open to more improvements. 仍然需要更多改进。
You could obtain delegates directly representing the getter and setter method: 您可以获得直接代表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());
It really depends on how often you're going to be calling it. 这实际上取决于您要多久调用一次。 If it isn't massive throughput, then fine - but note that the reflection-based
GetValue
/ SetValue
are pretty slow. 如果不是很大的吞吐量,那很好-但是请注意,基于反射的
GetValue
/ SetValue
相当慢。 You could cache the delegates, but another simple approach might be to look at HyperDescriptor - this uses the same API as PropertyDescriptor
(so you again get GetValue
/ SetValue
), but it uses dynamic methods underneath. 您可以缓存委托,但是另一种简单的方法可能是查看HyperDescriptor-它使用与
PropertyDescriptor
相同的API(因此您再次获得GetValue
/ SetValue
),但是它在下面使用了动态方法。 The API then is something like: 然后,API类似于:
PropertyDescriptor prop = TypeDescriptor.GetProperties(type)["PropertyName"];
or 要么
PropertyDescriptor prop = TypeDescriptor.GetProperties(obj)["PropertyName"];
then 然后
object value = prop.GetValue(component);
prop.SetValue(component, newValue);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.