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

C# C中基于基类动态参数调用的子类查找方法#,c#,dynamic,C#,Dynamic,我有一个基类和一个接受接口的方法。我想在子类中找到与此接口最匹配的方法。例如: 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> {

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

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";
  }
}
抽象类基类
{
公共T获取(IPRAM参数){
返回提供(参数为动态);
}
公共摘要T提供(IPRAM参数);
}
类Impl:Base
{
提供公共字符串(IPRAM参数)
{
返回“默认值”;
}
公共字符串提供(ParamImplementation1参数)
{
返回“执行值1”;
}
公共字符串提供(ParamImplementation2参数)
{
返回“执行值2”;
}
}

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

为什么不检查
提供方法覆盖中
参数的实际类型

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";
    }
}
私有抽象类基类
{
公共T获取(IPRAM参数)
{
返回提供(参数);
}
公共摘要T提供(IPRAM参数);
}
私有类Impl:Base
{
提供公共重写字符串(IPRAM参数)
{
if(参数为ParamImplementation1)
返回“执行值1”;
if(参数为ParamImplementation2)
返回“执行值2”;
返回“默认值”;
}
}

您可以在默认的
provide(IParam参数)
方法中处理该问题

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";
}
私有只读IDictionary\u方法;
公共Impl(){
var methods=this.GetType().GetMethods(
BindingFlags.Public|
BindingFlags.NonPublic|
BindingFlags.Instance|
BindingFlags(层次结构);
var提供=方法
其中(m=>m.Name.Equals(“提供”,StringComparison.Ordinal)和&m.GetParameters().Length==1)
.ToList();
_方法=when.ToDictionary(m=>m.GetParameters().First().ParameterType,m=>m);
}
公共字符串提供(IParam参数){
方法信息方法信息;
if(dictionary.TryGetValue(param.GetType(),out methodInfo)){
return methodInfo.Invoke(这个,新对象[]{param});
}
返回“默认值”;
}
因此,检查类中名为
Provide
的方法,并将其保存在字典中。出于性能原因,我会将此词典存储在类成员中。然后,您可以询问字典是否有用于特定参数类型的方法


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

因此解决方案似乎是将
转换为
动态
,如下所示:

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";
  }
}
抽象类基类
{
公共T获取(IPRAM参数){
返回(此为动态)。提供(参数为动态);
}
公共摘要T提供(IPRAM参数);
}
类Impl:Base
{
提供公共字符串(IPRAM参数)
{
返回“默认值”;
}
公共字符串提供(ParamImplementation1参数)
{
返回“执行值1”;
}
公共字符串提供(ParamImplementation2参数)
{
返回“执行值2”;
}
}

这里的dynamic关键字没有任何区别,抽象方法的实现必须具有完全相同的签名。这就是为什么每次只调用Provide(IPRAM参数),在这种情况下,这一点永远不会改变。
paramementation1
paramementation1
的重载不是基本抽象类的一部分,因此当
base
调用
Provide
时,它只会返回它知道的
IParam
版本。创建该方法的意义何在通用的没有它,它的工作方式是一样的。@DavidG我同意,不需要泛型,我的错。我有很多不同的ipram实现,每一个都有不同的属性。拥有一个包含多个ifs的庞大方法会让人难以理解和测试。您是否也有很多
Base
实现?如果是这样的话,我只能认为反射是一个可能的解决方案。@Dmitry我已经回答了我自己的问题。我找到的解决方案是将
这个
转换为
动态
。已知
动态
在内部使用反射。正如我提到的,反射是我看到的唯一选择。你找到了最简洁的方法。干得好+1.