【问题标题】:Dynamically call overload methods of subclass动态调用子类的重载方法
【发布时间】:2020-09-25 02:41:17
【问题描述】:

我正在用 C# 编写一个游戏服务器,现在我遇到了一个问题,即调用适当的方法按其类型正确处理每条消息。这个简单的代码说明了我当前的解决方案:

public class DynamicBase
{
    public int Method(Abc abc) => 2;
    public virtual void Run()
    {
        IAbc abc = new Abc();
        Console.WriteLine(Method((dynamic)abc)); // print 2
        IAbc aha = new Aha();
        // expecting print 3
        Console.WriteLine(Method((dynamic)aha)); //Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
    }
}
public class DynamicSub : DynamicBase
{
    public int Method(Aha a) => 3;
}
public class Abc : IAbc { }
public class Aha : IAbc { }
public interface IAbc { }
//In Main(): new DynamicSub().Run();

Method((dynamic)aha) 的异常是由于运行时仅检查 DynamicBase 及其基类的 Method 重载。如果我希望它在DynamicSub 中调用Method,那么我需要在基类中使用完全相同的代码覆盖Run

那么,如何在没有覆盖的情况下实现这种行为?

如果不是,我如何通过以编程方式复制虚拟方法(我的意思是 IL 代码)为子类动态发出 Run 的覆盖?这样我的用户(我的库)就不必自己将Run 方法复制到子类。

【问题讨论】:

  • 如果某些继承者DynamicSub2 没有Method(Aha a),应该为Console.WriteLine(Method((dynamic)aha)); 调用什么?
  • 您正试图实现非常奇怪的行为。您永远不应该尝试在基类中调用派生类方法。你想解决什么问题?
  • @GuruStron 抛出 RuntimeBinderException。如果我想使异常保持沉默,那么我将拥有Method(object o)
  • @VladaxLe 说我有一个PeerBase 类来处理来自客户端的请求。它反序列化对 POCO 的传入请求。每个 POCO 将由一个适当的 Method 以不同方式处理,它充当子类的接口
  • C# 和其他 OOP 语言在编译时或运行时解析方法。虚拟方法在运行时解析,重载方法在编译时解析。我的情况是我试图调用重载方法,它们在编译时解决,所以我通过强制 thisdynamic 在运行时解决它。

标签: c# .net dynamic cil


【解决方案1】:
    Console.WriteLine(Method((dynamic)aha)); 

这会在编译时解析Method,实际上只有DynamicBase.Method

您想要的是动态解析Method,这意味着您调用该方法的引用必须是dynamic

Console.WriteLine(((dynamic)this).Method((dynamic)aha));

请注意,对于您想要实现的任何目标,很可能有更多类型安全的解决方案。如果您正在努力规避 C# 的所有类型安全,您可能需要研究更动态的语言 - 带有 NodeJS 的 JavaScript 是一个不错的选择。

【讨论】:

  • “还有更多类型安全的解决方案”。我之前确实为参数中的每个对象类型维护了一个委托字典,但它比动态慢得多。我还有一个Method(Object obj) 来处理我不知道的所有参数类型,所以避免处理RuntimeBinderException 会影响性能。
猜你喜欢
  • 1970-01-01
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2018-01-22
相关资源
最近更新 更多