Я пишу на стороне клиента для службы 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 });
}
....
}
Я пытаюсь вызвать метод GetWhwhat (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.Я понимаю, что наследование интерфейса не работает как наследование классов;но я не уверен, как обойти эту ошибку компилятора.Я уже пытался добавить новую реализацию ServiceCall внутри класса MyServiceClient, чтобы расширить ее в базе - но ошибка компилятора не изменилась.
Кстати, если я изменю свою реализацию ServiceClient на базу из IMyServiceClient, она работает.Кроме того, вызов только client.GetWhwhat (index) (который вызывает метод SyncCall) компилируется и работает просто отлично.
Может помочь любая идея о том, что происходит или что ищет компилятор.Спасибо.