2010-07-14 56 views
0

我正在爲支持同步和異步調用的WCF服務編寫客戶端,而無需在合同中的每個方法的通道中實現5-6種不同的方法。C#:WCF:接口繼承和鑄造問題

我有一個基本接口(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

無後顧之憂;自己解決吧! – user392005 2010-07-14 23:06:49

+0

偉大 - 接受你自己的答案然後人們不會繼續看着它試圖回答! :) – nitzmahone 2010-07-16 03:37:27

回答

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。

1

該問題與接口繼承無關。一般來說,泛型不是covariantServiceClient<IMyServiceClient>不能轉換爲ServiceClient<IServiceClient>,即使IMyServiceClient繼承自IServiceClient