按类型动态调度仅在运行时已知

Sam*_*erg 5 c# reflection

我一直在代码中遇到对相同模式的需求,这经常需要验证对象中所有属性的值。伪代码如下所示:

bool ValidateMe(object c) {
   var properties = GetProperties(c);
   foreach (var property in properties) {
        var value = property.GetValue(c);
        if (!IsValid(value)) {
            return false;
        }
   }
   return true;
}

bool IsValid(int value)
{
    return value != int.MaxValue;
}

bool IsValid(double value)
{
    return value != double.MaxValue;
}

bool IsValid(object value)
{
    return value != null;
}  // etc.
Run Code Online (Sandbox Code Playgroud)

我希望代码根据对象的类型(可以通过调用property.PropertTypevalue.GetType()假设值不为空来找到)动态地将值分派到正确的方法。

我发现实现这项工作的唯一方法是这样的:

interface IValidator {
    bool IsValid(object value);
}

class PredicateValidator<T> : IValidator {
    private Predicate<T> method;
    PredicateValidator(Predicate<T> method) {
        this.method = method;
    }

    bool IsValid(object value) {
        return IsValid((T) value);
    }

    bool IsValid(T value) {
        return method.invoke(value);
    }
}


var validationsByType = new Dictionary<Type,IValidator>();
validationsByType[typeof(double)]=new PredicateValidator<double>(IsValid);
validationsByType[typeof(double)]=new PredicateValidator<int>(IsValid);
Run Code Online (Sandbox Code Playgroud)

然后 Map 可以按类型将对象分派到正确的方法:

object value = property.GetValue(c);
bool result = validationsByType[c.GetType()].IsValid(value);
Run Code Online (Sandbox Code Playgroud)

是否有原生 C#(即语言功能)可以在运行时按类型进行动态分派?

Sam*_*erg 8

dynamic关键字将正确执行向下转换。所以上面的代码修改为:

bool ValidateMe(object c) {
   var properties = GetProperties(c);
   foreach (var property in properties) {
        var value = property.GetValue(c);
        if (!IsValid((dynamic) value)) {
            return false;
        }
   }
   return true;
}

bool IsValid(int value)
{
    return value != int.MaxValue;
}

bool IsValid(double value)
{
    return value != double.MaxValue;
}
Run Code Online (Sandbox Code Playgroud)

然后,.NET 运行时搜索要调用的最具体的方法签名。我之前认为这只dynamic适用于Duck Typing,但它也适用于动态分派到重载方法。