繁体   English   中英

在包括接口的类型之间切换

[英]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
};

...,然后在之前的循环中使用Item1Item2

您可以使用as运算子

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

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM