【问题标题】:Generic methods with delegate parameters带有委托参数的通用方法
【发布时间】:2026-02-23 14:55:01
【问题描述】:

我正在尝试创建两个泛型方法,其中一个是 void,另一个具有返回类型。 void 方法采用Action 委托,另一个采用Func 委托。 void 方法的实现是这样的:

 public static void ExecuteVoid<T>(Action<T> actionToExecute)
    {
        string endpointUri = ServiceEndpoints.GetServiceEndpoint(typeof(T));

        using (ChannelFactory<T> factory = new ChannelFactory<T>(new BasicHttpBinding(), new EndpointAddress(endpointUri)))
        {
            T proxy = factory.CreateChannel();

            actionToExecute(proxy);
        }
    }

这很好用,但我在使用非 void 方法时遇到了问题:

public static T ExecuteAndReturn<T>(Func<T> delegateToExecute)
    {
        string endpointUri = ServiceEndpoints.GetServiceEndpoint(typeof(T));

        T valueToReturn;

        using (ChannelFactory<T> factory = new ChannelFactory<T>(new BasicHttpBinding(), new EndpointAddress(endpointUri)))
        {
            T proxy = factory.CreateChannel();

            valueToReturn = delegateToExecute();
        }

        return valueToReturn;
    }

现在,当我尝试像这样调用方法时:

var result = ServiceFactory.ExecuteAndReturn((IMyService x) => x.Foo());

我得到这个编译错误:

The type arguments for method 'ServiceFactory.ExecuteAndReturn<T>(System.Func<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.

Foo() 在这种情况下是一个没有参数的方法,它返回一个object。然后我尝试通过显式指定类型来调用该方法:

var result = ServiceFactory.ExecuteAndReturn<IMyService>(x => x.Foo());

但现在我得到另一个例外说法

Delegate 'IMyService' does not take 1 arguments.

我真的迷路了。任何帮助表示赞赏。

【问题讨论】:

  • IMyService的定义是什么?
  • @terrybozzio 那么在这种情况下x 的类型是什么?需要以某种方式指定类型。

标签: c# generics delegates


【解决方案1】:

您可能会将返回类型与代理类型混淆。如果您将参数指定为Func&lt;T&gt;,则T 需要是函数的返回类型,而不是代理类型。但是,您还需要指定代理类型,以便获得正确的服务端点和通道工厂。因此,您实际上需要 两个 类型参数:一个用于代理,一个用于返回类型。我还假设函数委托需要将初始化的代理作为参数;否则,这个包装方法将毫无意义。

public static TResult ExecuteAndReturn<TProxy, TResult>(
    Func<TProxy, TResult> delegateToExecute)
{
    string endpointUri = ServiceEndpoints.GetServiceEndpoint(typeof(TProxy));

    TResult valueToReturn;

    using (ChannelFactory<TProxy> factory = new ChannelFactory<TProxy>(new BasicHttpBinding(), new EndpointAddress(endpointUri)))
    {
        TProxy proxy = factory.CreateChannel();

        valueToReturn = delegateToExecute(proxy);
    }

    return valueToReturn;
}

编辑:出现编译器错误是因为(IMyService x) =&gt; x.Foo()Func&lt;T&gt; 委托不兼容。在编写匿名函数时,推断的类型是匿名函数本身的类型,而不是它碰巧调用的方法。在这种情况下,匿名函数接受IMyService 类型的单个参数,并返回object(作为Foo 的返回类型)。因此,这个匿名方法的正确委托应该是Func&lt;IMyService, object&gt;

【讨论】:

  • 我相信我过去确实写过一些与这个包装方法非常相似的东西,所以感觉很熟悉;-)
【解决方案2】:

您已将参数定义为 func&lt;x&gt; 即没有参数的委托,但随后将其调用为 Func&lt;x,y&gt; 即接受 1 个参数 IMyService 的委托,因此出现错误“Delegate 'IMyService' does not take 1 arguments”

【讨论】: