类型,包括界面之间进行切换(Switch between types including inter

2019-10-19 18:09发布

我有一个一组重载的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)](); 在寻找List<int>键集合中,没有IEnumerable<int>

我试图避免反射(并保持它作为最后的手段)。 有没有一种方法类似Type.IsAssignableFrom(Type)的接口的方法? 换句话说,我想请检查是否提供类型实现IEnumerable<int> ,而不是它。

Answer 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在循环早期。



Answer 2:

您可以使用作为运算符

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

}


文章来源: Switch between types including interfaces