Performans önemliyse, CreateDelegate
yapısından daha iyi olacağınızı düşünüyorum. Önceden yöntemin imzasını bildiğinizden, burada PropertyInfo
'un sadece GetGetMethod
ve GetSetMethod
olduğu gibi, doğrudan aynı imzayla çok yöntemi yürütmek için bir temsilci oluşturabilirsiniz. Temsilciler için bazı mantık (bir yöntem tanıtıcısı yoktu) oluşturmanız gerekiyorsa ifadeler daha uygun olacaktır.Ben bu soruna farklı yolları üzerinde bazı kıyaslama yaptı: yaklaşık 10000000 aramalar için
Func<S, T> Getter;
Action<S, T> Setter;
PropertyInfo Property;
public void Initialize(Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
Property = body.Member as PropertyInfo;
//approaches:
//Getter = s => (T)Property.GetValue(s, null);
//Getter = memberSelector.Compile();
//ParameterExpression inst = Expression.Parameter(typeof(S));
//Getter = Expression.Lambda<Func<S, T>>(Expression.Property(inst, Property), inst).Compile();
//var inst = Expression.Parameter(typeof(S));
//Getter = Expression.Lambda<Func<S, T>>(Expression.Call(inst, Property.GetGetMethod()), inst).Compile();
//Getter = (Func<S, T>)Delegate.CreateDelegate(typeof(Func<S, T>), Property.GetGetMethod());
//Setter = (s, t) => Property.SetValue(s, t, null);
//var val = Expression.Parameter(typeof(T));
//var inst = Expression.Parameter(typeof(S));
//Setter = Expression.Lambda<Action<S, T>>(Expression.Call(inst, Property.GetSetMethod(), val),
// inst, val).Compile();
//Setter = (Action<S, T>)Delegate.CreateDelegate(typeof(Action<S, T>), Property.GetSetMethod());
}
//Actual calls (tested under loop):
public T Get(S instance)
{
//direct invocation:
//return (T)Property.GetValue(instance, null);
//calling the delegate:
//return Getter(instance);
}
public void Set(S instance, T value)
{
//direct invocation:
//Property.SetValue(instance, value, null);
//calling the delegate:
//Setter(instance, value);
}
Sonuçları - (Get Set):
GetValue-SetValue (direkt): 3800 ms, 5500 ms
GetValue-SetValue (temsilci): 3600 ms, 5300 ms
derlenmiş ifadeler:
Get: Expression.Property: 280 ms
Expression.Call: 280 ms
direct compile: 280 ms
Set: 300 ms
temsilci oluşturun: 130 ms, 135 ms
doğrudan mülkiyet çağrı: 70 ms, 70 ms
Ben senin olayda, yazardı:
public static Func<S, T> BuildGetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetGetMethod().CreateDelegate<Func<S, T>>();
}
public static Action<S, T> BuildSetAccessor<S, T>(Expression<Func<S, T>> propertySelector)
{
return propertySelector.GetPropertyInfo().GetSetMethod().CreateDelegate<Action<S, T>>();
}
// a generic extension for CreateDelegate
public static T CreateDelegate<T>(this MethodInfo method) where T : class
{
return Delegate.CreateDelegate(typeof(T), method) as T;
}
public static PropertyInfo GetPropertyInfo<S, T>(this Expression<Func<S, T>> propertySelector)
{
var body = propertySelector.Body as MemberExpression;
if (body == null)
throw new MissingMemberException("something went wrong");
return body.Member as PropertyInfo;
}
Yani şimdi diyorsunuz:
TestClass cwp = new TestClass();
var access = BuildGetAccessor((TestClass t) => t.AnyValue);
var result = access(cwp);
Bu simpl değil mi? er ?? Tam olarak işlemek için genel bir sınıf here yazmıştı. "Çünkü benim uygulamasının yapısının" < T >
"Birlikte yöntemleri kullanamaz çünkü böylece yapıyorum" - Bu senin NETFX sürümünü <2.0 anlamına mı geliyor? Neden uygulamanızda jenerik kullanmıyorsunuz? –
Ayrıca, mülkler için delege oluşturarak gelmez Ne yansıması ile ne ilgisi var ve ne sorun yansıma kullanarak çözmeye çalışıyorsunuz? –
Delegeler çok daha iyi performansa sahiptir ve dinamik olarak kullanılabilir. Dinamik çağrıyı kullanmanız gerektiğinde tercih edilen seçeneklerdir. – GregRos