基于C#中基类中的动态参数调用在子类中查找方法

本文关键字:子类 查找 调用 方法 动态 基类 基于 参数 | 更新日期: 2023-09-27 18:28:03

我有一个基类,它有一个接受接口的方法。我想在子类中找到最匹配这个接口的方法。例如:

abstract class Base<T>
{
  public T Get(IParam parameter){
    return Provide(parameter as dynamic);
  }
  public abstract T Provide(IParam parameter);
}
class Impl<string> : Base<string>
{
  public string Provide(IParam parameter)
  {
    return "default value";
  }
  public string Provide(ParamImplementation1 parameter)
  {
    return "value for implementation 1";
  }
  public string Provide(ParamImplementation2 parameter)
  {
    return "value for implementation 2";
  }
}

不幸的是,每次都会返回默认值。当实际实现在子类中时,dynamic关键字似乎不起作用。有什么办法让它发挥作用吗?

基于C#中基类中的动态参数调用在子类中查找方法

因此,解决方案似乎是将this强制转换为dynamic,如下所示:

abstract class Base<T>
{
  public T Get(IParam parameter){
    return (this as dynamic).Provide(parameter as dynamic);
  }
  public abstract T Provide(IParam parameter);
}
class Impl<string> : Base<string>
{
  public string Provide(IParam parameter)
  {
    return "default value";
  }
  public string Provide(ParamImplementation1 parameter)
  {
    return "value for implementation 1";
  }
  public string Provide(ParamImplementation2 parameter)
  {
    return "value for implementation 2";
  }
}

为什么不检查Provide方法重写中parameter的真实类型?

private abstract class Base<T>
{
    public T Get(IParam parameter)
    {
        return Provide(parameter);
    }
    public abstract T Provide(IParam parameter);
}
private class Impl : Base<string>
{
    public override string Provide(IParam parameter)
    {
        if (parameter is ParamImplementation1)
            return "value for implementation 1";
        if (parameter is ParamImplementation2)
            return "value for implementation 2";
        return "default value";
    }
}

您可以在默认的provide(IParam param)方法中处理它。

private readonly IDictionary<Type, MethodInfo> _methods;
public Impl() {
    var methods = this.GetType().GetMethods(
        BindingFlags.Public |
        BindingFlags.NonPublic |
        BindingFlags.Instance |
        BindingFlags.FlattenHierarchy);
    var provide = methods
        .Where(m => m.Name.Equals("Provide", StringComparison.Ordinal) && m.GetParameters().Length == 1)
        .ToList();
    _methods = when.ToDictionary(m => m.GetParameters().First().ParameterType, m => m);
}
public string Provide(IParam param) {
    MethodInfo methodInfo;
    if (dictionary.TryGetValue(param.GetType(), out methodInfo)) {
        return methodInfo.Invoke(this, new object[] { param });
    }
    return "default value";
}

因此,您可以检查类中名称为Provide的方法,并将其保存在字典中。出于性能原因,我会将此词典存储在类成员中。然后,您可以询问字典是否有适合您特定参数类型的方法。

使用此技术,在添加新的Provide()实现时不必更改其他方法或切换/case语句。