我注意到Delegate类有一个Target属性,(可能)返回委托方法将执行的实例。我想做这样的事情:
void PossiblyExecuteDelegate(Action<int> method)
{
if (method.Target == null)
{
// delegate instance target is null
// do something
}
else
{
method(10);
// do something else
}
}
调用它时,我想做类似的事情:
class A
{
void Method(int a) {}
static void Main(string[] args)
{
A a = null;
Action<int> action = a.Method;
PossiblyExecuteDelegate(action);
}
}
但是当我尝试构造委托时,我得到一个ArgumentException(委托给一个实例方法不能有一个null'this')。我想做什么,我该怎么做?
答案 0 :(得分:15)
AHAH! found it!
您可以使用CreateDelegate重载创建一个打开的实例委托,使用一个委托,并明确指定隐含的'this'第一个参数:
delegate void OpenInstanceDelegate(A instance, int a);
class A
{
public void Method(int a) {}
static void Main(string[] args)
{
A a = null;
MethodInfo method = typeof(A).GetMethod("Method");
OpenInstanceDelegate action = (OpenInstanceDelegate)Delegate.CreateDelegate(typeof(OpenInstanceDelegate), a, method);
PossiblyExecuteDelegate(action);
}
}
答案 1 :(得分:1)
要执行此操作,您必须将static
方法传递给PossiblyExecuteDelegate()
。这将为您提供null
Target
。
class A
{
void Method(int a) {}
static void Method2(int a) {}
static void Main(string[] args)
{
PossiblyExecuteDelegate(A.Method2);
A a = new A();
PossiblyExecuteDelegate(a.Method);
}
}
编辑 可以通过反射将委托传递给没有目标的实例方法,但不能使用标准编译代码。
答案 2 :(得分:0)
使用Delegate.CreateDelegate可以完全使用签名的重载:
CreateDelegate (Type, object, MethodInfo)
如果指定&#34; null&#34;对于第二个参数(目标) 然后你必须在委托类型中添加一个额外的参数,它指定实例类型,当你调用委托时,实例必须作为第一个参数传递,然后是&#34; real&#34;方法的参数。
class Test
{
public int AddStrings(string a, string b)
{
return int.Parse(a) + int.Parse(b);
}
static void Main()
{
var test = new Test();
var methodInfo = test.GetType().GetMethod("AddStrings");
// note the first extra parameter of the Func, is the owner type
var delegateType = typeof(Func<Test, string, string, int>);
var del = Delegate.CreateDelegate(delegateType, null, methodInfo);
var result = (int)del.DynamicInvoke(test, "39", "3");
}
}