2011-11-07 88 views
1

我有自定義控件,並且我有接口這個控件暴露給它的用戶。使用通用類實現非通用接口

public interface ILookupDataProvider 
    { 
     void GetDataAsync(string parameters, Action<IEnumerable<object>> onSuccess, Action<Exception> onError); 
    } 

需要實現它,像這樣:

public class LookupDataProvider<T> : ILookupDataProvider 
    { 

     public void GetDataAsync(string parameters, Action<IEnumerable<T>> onSuccess, Action<Exception> onError) 
     { 
      var query = new EntityQuery<T>(); 
      this.entityManager.ExecuteQueryAsync(
       query, 
       op => 
        { 
         if (op.CompletedSuccessfully) 
         { 
          onSuccess(op.Results); 
         } 
         else if (op.HasError) 
         { 
          onError(op.Error); 
         } 
        }); 
     } 
    } 

所以,我怎麼告訴這個通用方法是真正實現的接口?

回答

1

如果你可以改變類是可以做到這一點的一般方法:

public class LookupDataProvider : ILookupDataProvider 
{ 

    public void GetDataAsync<T>(string parameters, Action<IEnumerable<T>> onSuccess, Action<Exception> onError) 
    { 

    } 

    void ILookupDataProvider.GetDataAsync(string parameters, Action<IEnumerable<object>> onSuccess, Action<Exception> onError)   
    { 
     this.GetDataAsync<Object>(parameters, onSuccess, onError); 
    } 

} 

編輯 在問候柯克的評論,你需要移動的類型參數的方法。儘管你可以把它留在課堂上,也可以導致有趣的事情。例如運行這段代碼:

class Program 
{ 
    static void Main(string[] args) 
    { 
     var b = new Foo<Guid>(); 
     b.Bar(); 

     Console.ReadLine(); 
    } 
} 



public class Foo<T> 
{ 

    public void Bar<T>() 
    { 
     Console.WriteLine("Bar<T>() : " +typeof(T).Name); 
    } 

    public void Bar()   
    { 

     Console.WriteLine("Bar() : " + typeof(T).Name); 
     this.Bar<string>(); 
    } 

} 

這其實是一個警告(我很驚訝,它不被視爲一個例外)

+0

我認爲這是正確的解決方案 - 除了爲什麼要改變類不再使用泛型參數? –

+0

@KirkWoll看到我的編輯 – JoshBerke

+0

但我的觀點是,您可以在類中保留類型參數,但仍然使用顯式接口實現,就像您在原始答案中所做的一樣。我並不是說它本身更好,但它涉及更少地改變OP的原始代碼,這似乎是最好的。 –

1

右鍵單擊ILookupDataProvider。選擇Implement Interface。填寫提供的方法而不更改簽名。


編輯:我以爲會有人來就到這裏,並告訴你如何將呼叫轉發。好吧。

public class LookupDataProvider<T> : ILookupDataProvider 
{ 
    public void GetDataAsync(
    string parameters, 
    Action<IEnumerable<object>> onSuccess, 
    Action<Exception> onError) 
    { 
    Action<IEnumerable<T>> onSuccessGeneric = x => onSuccess(x.OfType<object>()); 
    this.GetDataAsync(parameters, onSuccess, onError); 
    } 

    public void GetDataAsync(
    string parameters, 
    Action<IEnumerable<T>> onSuccess, 
    Action<Exception> onError) 
    { 
    // as you had it before. 
    } 
} 

,如果你想轉發的方法只能通過接口訪問,使用此方法的簽名:

public void ILookupDataProvider.GetDataAsync(
    string parameters, 
    Action<IEnumerable<object>> onSuccess, 
    Action<Exception> onError) 
1

類型參數沒有在派生類中的任何一個帶有這樣或那樣的是接口的一個實現。

例如:

interface I 
{ 
    int X { get; } 
} 

class A : I 
{ 
    int X { get; set; } 
} 

class B<T> : I 
{ 
    void F(T t) {} 
    int X { get; set; } 
} 

博特A和B的一

+0

我覺得OP被提出的觀點是,由於簽名是不兼容,通用版本不滿足界面。 –

1

實現如果您在界面上單擊鼠標右鍵,並選擇實現接口,它會爲你做的,但方式你有界面設計,它不會匹配界面的定義。

以使它們匹配,你可以做以下(現爲執行將匹配接口的簽名):

public interface ILookupDataProvider<T> 
    { 
     void GetDataAsync(string parameters, Action<IEnumerable<T>> onSuccess, Action<Exception> onError); 
    } 

    public class LookupDataProvider<T> : ILookupDataProvider<T> 
+0

+1如果你可以改變接口爲通用的,這是理想的解決方案恕我直言, – JoshBerke

+0

@Josh,通常,我*使用接口的全部原因是提供*非泛型*方式來訪問我的API 。 (例如'IEnumerable'與'IEnumerable ') –