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.