如何使C#Create.Delegate支持继承?
我有以下类型层次结构:如何使C#Create.Delegate支持继承?,c#,.net,reflection,delegates,C#,.net,Reflection,Delegates,我有以下类型层次结构: public abstract class Parent { } public class Child : Parent { public Task SayAsync(string arg) { Console.WriteLine(arg); return Task.CompletedTask; } } 我需要做到以下几点: 在运行时创建Parent的任何实例(这已经通过调用Func解决了,我在代码的其他
public abstract class Parent { }
public class Child : Parent
{
public Task SayAsync(string arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
}
我需要做到以下几点:
- 在运行时创建
的任何实例(这已经通过调用Parent
解决了,我在代码的其他地方获得了该实例)Func
- 然后(在该实例上)调用所有
方法(它们总是返回public
并接受任务
作为参数),并传入非常量的字符串
arg
缓存的委托
,因此在启动时,我将创建委托,然后在需要时缓存并使用这些委托
下面是我为Child
所做的一个显式示例,该示例很有效,但我无法弄清楚如何使委托接受父级
(因为我在编译时不知道类型)
//如果我将Child更改为Parent,我会得到“无法绑定到目标方法,因为其签名或安全透明性与委托类型的签名或安全透明性不兼容”
私有委托任务调用程序(子实例,字符串arg);
void Main()
{
var instance=new Child();//这将通过调用Func获得
var methodWithArg=instance.GetType().GetMethod(“SaySync”);
var func=GetDelegateWithArg(methodWithArg);
func(例如“Foo”);
}
私有静态调用程序GetDelegateWithArg(MethodInfo方法)
{
对象指针=null;
return(Invoker)Delegate.CreateDelegate(typeof(Invoker)、指针、方法);
}
非常感谢任何有助于我实现目标的想法或备选方案。您可以尝试使用表达式树生成代理:
public abstract class Parent { }
public class Child : Parent
{
public Task SayAsync(string arg)
{
Console.WriteLine(arg);
return Task.CompletedTask;
}
}
public delegate Task Invoker(Parent instance, string arg);
class Program
{
static void Main(string[] args)
{
Parent instance = new Child(); // This will be obtained by calling a Func<Parent>
var methodWithArg = instance.GetType().GetMethod("SayAsync");
var func = GetDelegateWithArg(methodWithArg);
func(instance, "Foo");
}
private static Invoker GetDelegateWithArg(MethodInfo method)
{
var instanceParameter = Expression.Parameter(typeof(Parent));
var argParameter = Expression.Parameter(typeof(string));
var body = Expression.Call(
Expression.Convert(instanceParameter, method.DeclaringType),
method,
argParameter);
var lambda = Expression.Lambda<Invoker>(body, instanceParameter, argParameter);
return lambda.Compile();
}
}
公共抽象类父{}
公共类子级:父级
{
公共任务sayanc(字符串arg)
{
控制台写入线(arg);
返回Task.CompletedTask;
}
}
公共委托任务调用程序(父实例,字符串arg);
班级计划
{
静态void Main(字符串[]参数)
{
父实例=新的子实例();//这将通过调用Func获得
var methodWithArg=instance.GetType().GetMethod(“SaySync”);
var func=GetDelegateWithArg(methodWithArg);
func(例如“Foo”);
}
私有静态调用程序GetDelegateWithArg(MethodInfo方法)
{
var instanceParameter=Expression.Parameter(typeof(Parent));
var argParameter=Expression.Parameter(typeof(string));
var body=Expression.Call(
表达式.Convert(instanceParameter,方法.DeclaringType),
方法,,
参数);
var lambda=表达式.lambda(主体、instanceParameter、argParameter);
返回lambda.Compile();
}
}
生成的委托仍然非常快,尽管可能比Delegate.CreateDelegate()方法创建的委托慢一点。可能尝试将目标实例传递给GetDelegateWithArg方法,并更改调用程序的签名以仅接收参数。大概是这样的:
private delegate Task Invoker(string arg);
private static Invoker GetDelegateWithArg(MethodInfo method, object target)
{
return (Invoker)Delegate.CreateDelegate(typeof(Invoker), target, method);
}
在建议的更改之后,您可以通过一个参数将实例传递给委托创建者和incoke func:
func("Foo");
这是一个有趣的答案,但有一个问题是,我需要在给定实例上执行每个调用,在您的解决方案中,我必须在每次创建一个实例时创建
委托。否?是的,您必须为每个实例创建委托。通过提供实例,您将确保该方法将在实例级别上创建,然后在给定实例上执行。您可以查看。感谢您的澄清,由于为每个实例创建委托的性能限制,我将无法使用此方法。但不管怎样,投票率还是上升了@到目前为止,帕维尔的答案正是我想要的。这太棒了!事实上,我通过将程序集标记为[assembly:SecurityTransparent]
来补偿额外的开销,现在它比委托更快
func("Foo");