我正在为支持同步和异步调用的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方法)编译并正常工作。
任何关于发生了什么或者编译器正在寻找什么的想法都会有所帮助。感谢。
答案 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。