接口混乱的 C# 通用 ClientBase

Luc*_*cas 5 c# generics wcf

ClientBase的 C# 定义是:

public abstract class ClientBase<TChannel> : ICommunicationObject, 
    IDisposable
where TChannel : class
Run Code Online (Sandbox Code Playgroud)

这清楚地表明了classTChannel类型的约束。据我所知,这意味着在声明自己的类时不能使用泛型的接口类型。因此,鉴于如此声明的服务:

public IMyService
...
public MyService : IMyService
...
Run Code Online (Sandbox Code Playgroud)

这应该有效:

public MyServiceClient : ClientBase<MyService> 
Run Code Online (Sandbox Code Playgroud)

这应该不是

public MyServiceClient : ClientBase<IMyService> 
Run Code Online (Sandbox Code Playgroud)

但显然我不理解,因为该示例显示了以下声明:

public partial class SampleServiceClient : 
    System.ServiceModel.ClientBase<ISampleService>, ISampleService
Run Code Online (Sandbox Code Playgroud)

更重要的是,我试图抽象身份验证,并使用实用程序方法正确关闭客户端:

    public TResult WithClient<TInterface, T, TResult>(T service, 
        Func<TInterface, TResult> callback)
        where T : ClientBase<TInterface>, TInterface
    {
        service.ClientCredentials.UserName.UserName = userName;
        service.ClientCredentials.UserName.Password = password;

        try
        {
            var result = callback(service);
            service.Close();
            return result;
        }
        catch (Exception unknown)
        {
            service.Abort();
            throw unknown;
        }
    }
Run Code Online (Sandbox Code Playgroud)

但这给了我编译器错误:

The type 'TInterface' must be a reference type in order to use it as parameter 'TChannel' in the generic type or method 'ClientBase<TChannel>'
Run Code Online (Sandbox Code Playgroud)

有人可以清除这里的混乱吗?我究竟做错了什么?

- - 更新 - -

根据@InBetween,解决方案是将where TInterface : class约束添加到我的实用程序方法中:

    public TResult WithClient<TInterface, T, TResult>(T service, 
        Func<TInterface, TResult> callback)
        where TInterface : class
        where T : ClientBase<TInterface>, TInterface
    {
        service.ClientCredentials.UserName.UserName = userName;
        service.ClientCredentials.UserName.Password = password;

        try
        {
            var result = callback(service);
            service.Close();
            return result;
        }
        catch (Exception unknown)
        {
            service.Abort();
            throw unknown;
        }
    }
Run Code Online (Sandbox Code Playgroud)

InB*_*een 5

class约束的约束一般类型的引用类型。根据定义,接口是一种引用类型。您不能做的是使用值类型作为泛型类型:ClientBase<int>将是编译时错误。

至于第二个错误,你没有约束TInterface,然后在ClientBase<TInterface>. 由于ClientBase将其泛型类型约束为引用类型 ( class),因此您需要相应地进行约束TInterface