2014-07-11 133 views
0

我想刪除具有可變數量的參數的System.Func集合的重複代碼。 (這用於允許代碼「掛鉤」到其他組件的邏輯中。) 因此,我試圖刪除幾個幾乎相同的方法,並使用泛型方法代替。嵌套泛型類型:重用外部類型參數

爲了使它工作,我將它們包裝在一個HookContainer類中,並使它實現了一個通用接口。

public interface IHookContainer 
{ 
    void Add<TFunc> (string filterName, int priority, KeyValuePair<string, TFunc> action); 
} 

public class HookContainer<T>:IHookContainer 
{ 
    Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>>(); 

    public void Add<T> (string filterName, int priority, KeyValuePair<string, T> action) 
    { 
     // Add an item to the Dictionary 
    } 
} 

這讓我把他們都在,我可以與類型

Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer>(){ 
{ 
    typeof(HookContainer<System.Func<object,object>>),new HookContainer<System.Func<object,object>>() 
}, 
// More dictionary entries like this (with more parameters) 
}; 


    public string AddFilter<T> (string filterName, T action, string filterTag = null, int priority=0) 
    { 

      KeyValuePair<string, T> data = new KeyValuePair<string, T> (filterTag, action); 
      if (containers.ContainsKey (typeof(T))) { 
        IHookContainer container = containers [typeof(T)]; 
        container.Add<T> (filterName, dictPriority, data); 


      } 

      return filterTag; 

    } 

現在我得到一個編譯錯誤說訪問一個字典:

cannot convert `System.Collections.Generic.KeyValuePair<string,T>' 
expression to type `System.Collections.Generic.KeyValuePair<string,T>' 

所以這是很明顯缺乏一些我認爲理所當然的信息。或者我想錯了。或兩者。 爲什麼不能將類型轉換爲...本身?

我明顯不能使用泛型類中的相同類型參數作爲泛型方法(如果已實現的接口)。可悲的是,這種類型也無法推斷。有什麼辦法可以做到這一點?

還有一個警告,即類型參數名稱與外部類型參數相同。我能告訴編譯器這是完全意圖的嗎?

感謝您的任何幫助。我使用C#4.0

更新:

我可以得到代碼與第二個類型參數聲明HookContainer和使用這種傳遞入Add方法工作。

所以它現在看起來是這樣的:

public class HookContainer<T,U>:IHookContainer 
{ 
    Dictionary<string,OrderedDictionary<string,T>> dict = new Dictionary<string, OrderedDictionary<string, T>>(); 
    public void Add<U> (string filterName, int priority, KeyValuePair<string, T> action) 
    { 
     // Add an item to the Dictionary 
    } 

}

這當然需要我去冗餘通過容器的類型兩次聲明字典時:

Dictionary<Type,IHookContainer> containers = new Dictionary<Type, IHookContainer>(){ 
{ 
typeof(HookContainer<System.Func<object,object>,System.Func<object,object>>),new HookContainer<System.Func<object,object>,System.Func<object,object>>() 
} 
}; 

所以雖然這可能有效,但它看起來和感覺很荒謬。有沒有什麼辦法只是(重新)使用一個單一的類型參數?

+0

我得到「非一般類型‘System.Collections.Specialized.OrderedDictionary’不能與類型參數一起使用。」 – MJVC

+0

我正在使用OrderedDictionary的這個實現https://github.com/johndkane/GenericOrderedDictionary/blob/master/Library/OrderedDictionary%602.cs – Arbelzapf

回答

2

更新

我誤解你的問題。你實現這個的方式,不是你想要的,我想。界面中的聲明與您在實現中需要的聲明不同。 在你的接口聲明中,你指定這個接口的實現應該有一個通用函數(可以用各種類型調用)。在你的實現中,你想限制這只是你在類中指定的類型。 類的實現將針對一種特定的類型。

I.e. IHookContainer接口指定您可以使用int,string等調用Add函數。而在HookContainer<string>中,只能使用字符串參數調用Add

更合適的實現你想要什麼,但你不能存儲在詞典是:

public interface IHookContainer<T> 
{ 
    Add(string filterName, int priority, KeyValuePair<string, T> action); 
} 

什麼解決方案可以(我可以做什麼)是將詞典更改爲列表並創建一個函數來檢索正確的IHookContainer<T>。或者在項目數量很大時保留字典,並通過鍵輸入正確的字典。

private List<object> containers = new List<object>(); 
private IHookContainer<T> GetCorrectHookContainer<T>() 
{ 
    // might need to add when not available? 
    return containers.OfType<IHookContainer<T>>().FirstOrDefault(); 
} 

AddFilter功能將是這樣的(僞代碼)

public void AddFilter<T>(...) 
{ 
    GetCorrectHookContainer<T>().Add(...); 
} 

老:

因爲你指定在你的函數的類型參數(再次),該T的類不同於函數中的T。通用函數中的參數T'隱藏'該類的T。你可以使用它。你不必在你的函數中指定它。您的實現可以是:

public void Add(string filterName, int priority, KeyValuePair<string, T> action) 
{ 
    // Add an item to the Dictionary 
} 

實例的使用:

var x = new HookContainer<int>(); 
x.Add("test", 1, new KeyValuePair<string,int>("test", 4)); 
+0

好吧,你說的話是有道理的,所以這是不可能的,除非我通過訪問它們的每種方法拖動2個完全相同的(但技術上不同的)類型參數? – Arbelzapf

+0

使接口本身變得通用(而不僅僅是方法)的問題是,我不能將它們全部放在同一個字典中,從而破壞了整個設置的重點。或者我錯了嗎? – Arbelzapf

+0

**更新**感謝您的支持解決方案,目前它似乎工作得很好 – Arbelzapf

1

看來這個問題是TFromAddTHookContainer是兩種不同的通用類型。

我不知道這是否是可能的,但我會用C的主要特徵,而不是(int argc, char[] argv)Func功能:

System.Func<int, object[], object> 
+0

這不行,恐怕。我無法將任何內容添加到詞典中。只要我把它放到IHookContainer ,當我試圖再次把它拿出來時它就會返回null。非常感謝你的時間,儘管 – Arbelzapf

+0

用我用來存儲掛鉤的示例更新了答案。 – MJVC

+0

我不明白你的更新回答:( – Arbelzapf