C#:WCF:接口继承和转换问题

时间:2010-07-14 20:42:04

标签: c# wcf inheritance interface compiler-errors

我正在为支持同步和异步调用的WCF服务编写客户端,而不必在通道中为合同中的每个方法实现5-6种不同的方法。

我有一个基本接口(IServiceClient)和一个基于此接口类型(ServiceClient)的泛型类,如下所示:

public interface IServiceClient { /* nothing here -- just for casting purpose */ }

public abstract class ServiceClient<TChannel> : ClientBase<TChannel> where TChannel : class, IServiceClient
{
    ....

    public T SyncCall<T>(string method, object[] args)
    {
        ....
        return (T)...
    }

    public ServiceCall<T> AsyncCall<T>(string method, object[] args)
    {
        return new ServiceCall<T>(this, method, args);
    }

    ....

    public class ServiceCall<T>
    {
        public ServiceCall(RemoteServiceClient<TChannel> service, string method, object[] args)
        {
            ...
        }

        ...

        public PageAsyncTask CreatePageAsyncTask(Action<T> onSuccess, Action<Exception> onFailure)
        {
            return new System.Web.UI.PageAsyncTask(...);
        }
    }
}

此外,还有另一个接口(实际合约)扩展基接口和基于派生接口的ServiceClient类的特定实现,如下所示:

[ServiceContract]
public interface IMyServiceClient : IServiceClient
{
    ....

    [OperationContract]
    string GetWhatever(int index);
    [OperationContract]
    IAsyncResult BeginGetWhatever(int index, System.AsyncCallback callback, object asyncState);
    string EndGetWhatever(System.IAsyncResult result);

    ....
}


public partial class MyServiceClient : ServiceClient<IMyServiceClient>
{
    ....

    public string GetWhatever(int index)
    {
        return SyncCall<string>("GetWhatever", new object[] { index });
    }
    public ServiceCall<string> GetWhateverAsync(int index)
    {
        return AsyncCall<string>("GetWhatever", new object[] { index });
    }

    ....
}

我尝试在控件中异步调用GetWhatever(int)方法,如下所示:

public class MyWebControl : WebControl
{
    private void HandleFailure(System.Exception e) { .... }
    public void CallService<T>(ServiceClient<IServiceClient>.ServiceCall<T> func, System.Action<T> onSuccess, System.Action<Exception> onFailure)
    {
        this.Page.RegisterAsyncTask(func.CreatePageAsyncTask(onSuccess, onFailure ?? (e => this.HandleFailure(e))));
    }

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);

        ....

        var client = new MyServiceClient(/*whatever*/);
        client.Open();
        CallService(client.GetWhateverAsync(index), this.OnResult, this.OnError);

        ....
    }

    public void OnResult(string result) { .... }
    public void OnError(Exception e) { .... }
}

我收到2个编译错误:

Error 1 The best overloaded method match for 'MyWebControl.CallService<string>>(IServiceClient>.ServiceCall<string>, System.Action<string>, System.Action<System.Exception>)' has some invalid arguments
Error 2 Argument 1: cannot convert from 'ServiceClient<IMyServiceClient>.ServiceCall<string>' to 'ServiceClient<IServiceClient>.ServiceCall<string>'

显然,编译器似乎无法弄清楚IMyServiceClient是否扩展了IServiceClient。我知道接口继承不像类继承那样工作;但我不知道如何解决这个编译器错误。我已经尝试在MyServiceClient类中添加一个新的ServiceCall实现来扩展它 - 但是编译器错误没有改变。

顺便说一句,如果我将我的ServiceClient实现更改为基于IMyServiceClient,它可以工作。另外,只调用client.GetWhatever(index)(调用SyncCall方法)编译并正常工作。

任何关于发生了什么或者编译器正在寻找什么的想法都会有所帮助。感谢。

2 个答案:

答案 0 :(得分:1)

问题与接口继承无关。事实上,泛型一般不是协变ServiceClient<IMyServiceClient>无法转换为ServiceClient<IServiceClient>,即使IMyServiceClient继承自IServiceClient

答案 1 :(得分:0)

通过更改我的控件中的CallService方法来解决它:

public void CallService<TChannel, T>(ServiceClient<TChannel>.ServiceCall<T> func, System.Action<T> onSuccess, System.Action<Exception> onFailure) where TChannel: class, IServiceClient
{ 
    this.Page.RegisterAsyncTask(func.CreatePageAsyncTask(onSuccess, onFailure ?? (e => this.HandleFailure(e)))); 
} 

THX。