2014-04-04 41 views
1

我有一套get函數的重載。每個人都有不同的輸入類型,但基本上是相同的簽名模式(如下):在包括接口的類型之間切換

string GetPropertyValue(int propId, string defaultValue) 
bool GetPropertyValue(int propId, bool defaultValue) 
int GetPropertyValue(int propId, int defaultValue) 
IEnumerable<string> GetPropertyValue(int propId, IEnumerable<string> defaultValues) 
IEnumerable<bool> GetPropertyValue(int propId, IEnumerable<bool> defaultValues) 
IEnumerable<int> GetPropertyValue(int propId, IEnumerable<int> defaultValues) 

我上簡化了API爲單個通用方法的工作(如下):

T GetPropertyValue<T>(int propId , T defaultValue) 

要實現這樣的方法,我試圖用一個字典(inspired by this answer)的類型來切換上的默認值:

var actionDico = new Dictionary<Type, System.Action> 
{ 
    /* since the type of `defaultValue` is `T`, I cannot use `(bool)defaultValue` for example 
     therefore casting to (object) before to escape Cast operator restriction. 
     Will not fail as the key of the dictionary is a matching type */ 
    {typeof(bool),() => dob.GetPropertyValue(propId, (bool)(object)defaultValue)}, 
    {typeof(int),() => dob.GetPropertyValue(propId, (int)(object)defaultValue)}, 
    {typeof(string),() => dob.GetPropertyValue(propId, (string)(object)defaultValue)} 
} 

隨着混凝土的類型,以前的實現是完全沒有(至少在我的情況下)。通話將使用actionDico[typeof(T)]();完成。

具有字典中,以下是罰款:

{typeof(IEnumerable<int>),() => dob.GetPropertyValue(propId, (IEnumerable<int>)(object)defaultValue)}, 

但呼叫通常使用它們實現IEnumerable<int>List<int>等)的對象來完成。在這種情況下,呼叫actionDico[typeof(T)]();正在尋找密鑰集合中的List<int>,而不是IEnumerable<int>

我試圖避免反思(並將它作爲最後的手段)。有沒有類似於Type.IsAssignableFrom(Type)接口的方法?換句話說,我想檢查提供的類型實現IEnumerable<int>而不是它。

+1

我不清楚你想要用字典做什麼*做什麼,或者你正在談論的「演員操作員限制」是什麼。請注意,您可以非常容易地使用'typeof(IEnumerable )' - List「List 」在哪裏? (僅列出*列表是爲了說明你爲什麼不想在例子中使用'typeof' - 無處)。 –

+0

@JonSkeet:請看看編輯 –

+2

它相當於'actionDico [defaultValue.GetType()]'。當然,你得到List <>而不是IEnumerable <>。所以字典沒有用,你必須枚舉類型來找到匹配。你當然堅持使用IsAssignableFrom(),它並不昂貴。 –

回答

1

你可以不看的類型在字典的方式。您可以通過鍵值對必須循環:

Type targetType = defaultValue.GetType(); 
foreach (var pair in dictionary) 
{ 
    if (pair.Key.IsAssignableFrom(targetType)) 
    { 
     // Use pair.Value 
    } 
} 

然而,在這一點上你有效剛剛得到一個List<Tuple<Type, Action>>,而不是一本字典,你是如何使用它的條款...所以,你可以改用:

List<Tuple<Type, Action>> actions = new List<Tuple<Type, Action>> 
{ 
    Tuple.Create(typeof(bool),() => dob.GetPropertyValue(propId, (bool) (object)defaultValue), 
    Tuple.Create(typeof(int),() => dob.GetPropertyValue(propId, (int) (object)defaultValue), 
    // etc 
}; 

...,然後只用在循環早期Item1Item2

+0

現在看起來像轉儲錯誤:)謝謝!如果可能的話,你能否詳細說一說你最後的評論?我不太明白你指的是什麼 –

+1

@MoslemBenDhaou:我已經添加了一個例子。基本上dictoinaries適用於鍵/值查找,但在這種情況下,您實際上無法通過鍵查找。 –

0

可以使用as operator

var isEnumerable = defaultValue as IEnumerable; 
if (isEnumerable != null) 
{ 

}