[英]Switch between types including interfaces
我為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)
為了實現這種方法,我嘗試使用字典( 受此答案啟發 )打開默認值的類型:
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)]();
在鍵集合(而不是IEnumerable<int>
內尋找List<int>
IEnumerable<int>
。
我正在努力避免反射(並將其保留為最后的手段)。 接口是否有類似於Type.IsAssignableFrom(Type)
方法的方法? 換句話說,我想檢查提供的類型是否實現了IEnumerable<int>
而不是它。
您無法以這種方式在字典中查找類型。 您必須遍歷鍵值對:
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
};
...,然后在之前的循環中使用Item1
和Item2
。
您可以使用as運算子
var isEnumerable = defaultValue as IEnumerable;
if (isEnumerable != null)
{
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.