-1

I'm writing a game server in C# and now I have a problem of calling appropriate method handling each message by its type correctly. My current solution illustrated in this simple code:

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();

The exception for Method((dynamic)aha) is due to the runtime only check for Method overloads of DynamicBase and its base class. If I want it to call Method in DynamicSub then I need to override the Run with exact the same code in base class.

So, how can I achieve this behavior without an override?

If not, how can I dynamically emit an override of Run for the sub class by programmatically copying the virtual method (I mean IL code)? So that my user (of my lib) doesn't have to copy the Run method to sub class by herself.

Hai Nguyen
  • 81
  • 10
  • What should be called for `Console.WriteLine(Method((dynamic)aha));` if some inheritor `DynamicSub2` will not have `Method(Aha a)`? – Guru Stron Jun 05 '20 at 19:46
  • You are trying to achieve very strange behavior. You should never try to call derived class methods inside base class. What problem are you trying to solve? – VladaxLe Jun 05 '20 at 20:11
  • @GuruStron A RuntimeBinderException is thrown. If I want to silent the exception then I will have `Method(object o)` – Hai Nguyen Jun 06 '20 at 06:00
  • @VladaxLe Say I'm having a `PeerBase` class that handle requests from client. It deserializes incoming requests to POCOs. Each POCO will be handled differently by an appropriate `Method` which acts as an interface for subclasses – Hai Nguyen Jun 06 '20 at 06:40
  • C# and other OOP languages resolve methods at compile time or run time. Virtual methods are resolved at run time, overload methods are resolved at compile time. My case here is I'm trying to call overload methods, they are resolved at compile time so I made it resolved at run time by forcing `this` as `dynamic`. – Hai Nguyen Jun 06 '20 at 11:12

1 Answers1

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

That resolves Method at compile time, which indeed will be only DynamicBase.Method.

What you want is dynamically resolve Method which means reference on which you call the method must be dynamic:

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

Note that most likely there is more type-safe solution to whatever you trying to achieve. If you are working hard to circumvent all type safety of C# you may want look into more dynamic languages - JavaScript with NodeJS is a good choice.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
  • "there is more type-safe solution". I did maintain a Dictionary of delegates for each object type in parameter before but it was much slower than dynamic. I also have a `Method(Object obj)` to handle all param types that I don't know so avoid handling `RuntimeBinderException` impact performance a lots. – Hai Nguyen Jun 06 '20 at 06:53