Я хочу знать, есть ли лучший способ (чем то, что я сейчас делаю) получить и сохранить ссылку на свойство в другом объекте, используя только имена строк объекта и свойства. В частности, есть ли лучший способ сделать это с новой динамической функциональностью .Net 4.0?
Вот то, что у меня сейчас есть.
У меня есть объект "PropertyReference<T>
", который принимает имя объекта и имя свойства в конструкторе.
Метод Initialize()
использует отражение для поиска объекта и свойства и сохраняет свойство Getter как Action<T>
, а свойство Setter - как Func<T>
.
Когда я на самом деле хочу вызвать свойство, я делаю что-то вроде этого:
int x = _propertyReference.Get();
или
_propertyReference.Set(2);
Вот мой 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();
}
}
}
Примечание: я не могу использовать функциональность "Emit", так как мне нужен этот код для работы на новом Windows Phone 7, который не поддерживает Emit.
UPDATE:
Только что сделал несколько тестов скорости после замены:
_action = (T a) => pi.SetValue(component, a, null);
_func = () => (T)pi.GetValue(component, null);
С
_action = Action<T>)Delegate.CreateDelegate(typeof(Action<T>),component,pi.GetSetMethod());
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
Как указано в dtb ниже.
Протестировано с помощью 100 000 вызовов свойства Get (). Вот результаты.
_func = () => (T)pi.GetValue(component, null)
заняло около 200 мс
_func = (Func<T>)Delegate.CreateDelegate(typeof(Func<T>), component, pi.GetGetMethod());
заняло около 10 мс
Огромная разница. Не ожидал этого, но круто!
Все еще открыт для дополнительных улучшений.