Открытый делегат - это делегат метода экземпляра без цели. Чтобы вызвать его, вы указываете цель в качестве первого параметра. Они представляют собой умный способ оптимизации кода, который в противном случае использовал бы отражение и имел бы низкую производительность. Для ознакомления с открытыми делегатами см. this . На практике вы бы использовали дорогостоящий код отражения для создания этих открытых делегатов, но тогда вы могли бы очень дешево вызывать их как простой вызов делегата.
Я пытаюсь написать код, который преобразует произвольный PropertyInfo в такой делегат для его установщика. Пока что я придумал следующее:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Test
{
class TestClass
{
static Action MakeSetterDelegate(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 rather than Action.
//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 delegate into an Action
Action 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 setter = MakeSetterDelegate(property);
TestClass instance = new TestClass();
setter(instance, 5);
}
}
}
Подобный код будет написан для геттера. Это работает, но делегат установщика использует DynamicInvoke для преобразования из Action > в Action