Polymorphism Through Extension Methods?

后端 未结 5 1057
有刺的猬
有刺的猬 2021-02-20 05:21

I have a class library which contain some base classes and others that are derived from them. In this class library, I\'m taking advantage of polymorphism to do what I want it t

相关标签:
5条回答
  • 2021-02-20 05:40

    No, that won't work.

    Extension methods are statically dispatched, using the same mechanism as overload resolution.

    If you have a variable of compile-time type Base, the compiler will always call the base extension method, regardless of the runtime type.

    Instead, you can make the base extension method check the runtime type and call the appropriate other extension method.

    0 讨论(0)
  • 2021-02-20 05:51

    I was looking for the same thing just now.

    You could add one more method to your extension class like this:

    public static void DoSomething(this Base myObj, Object dependency)
    {       
        if(myObj.IsSubclassOf(Base))
        {
          // A derived class, call appropriate extension method.  
          DoSomething(myObj as dynamic, dependency);
        }
        else
        {
            // The object is Base class so handle it.
        }
    } 
    

    You don't need the if/else check if the base class is abstract (or never used in the wild):

    public static void DoSomething(this Base myObj, Object dependency)
    { 
        DoSomething(myObj as dynamic, dependency);
    }
    

    [Edit] Actually this won't work in your case as you don't implement support for all derived objects (so could still get infinite recursion). I guess you could pass something to check for recursion but the given answer is the simplest. I'll leave this here as it might spark more ideas.

    0 讨论(0)
  • 2021-02-20 05:52

    Below is the minimal example showing how to mimic polymorphism with extension methods.

    void Main()
    {
        var elements = new Base[]{
            new Base(){  Name = "Base instance"},
            new D1(){    Name = "D1 instance"},
            new D2(){    Name = "D2 instance"},
            new D3(){    Name = "D3 instance"}
    
        };
    
        foreach(Base x in elements){
            x.Process();
        }
    }
    
    public class Base{
        public string Name;
    }
    public class D1 : Base {}
    public class D2 : Base {}
    public class D3 : Base {}
    
    
    public static class Exts{
    
        public static void Process(this Base obj){
            if(obj.GetType() == typeof(Base)) Process<Base>(obj); //prevent infinite recursion for Base instances
            else Process((dynamic) obj);
        }
    
        private static void Process<T>(this T obj) where T: Base
        {
            Console.WriteLine("Base/Default: {0}", obj.Name);
        }
    
        public static void Process(this D1 obj){
            Console.WriteLine("D1: {0}", obj.Name);
        }
    
        public static void Process(this D2 obj){
            Console.WriteLine("D2: {0}", obj.Name);
        }
    }
    

    Outputs:

        Base/Default: Base instance
        D1: D1 instance
        D2: D2 instance
        Base/Default: D3 instance
    
    0 讨论(0)
  • 2021-02-20 05:52

    If you can not use the keyword "dynamic" (older version of .NET), you can use reflection to achieve the same thing.

    In place of :

    Base base1 = new Child1();
    Extensions.DoSomething(base1 as dynamic);
    

    you can write :

    Base base1 = new Child1();
    
    MethodInfo method = typeof(Extensions).GetMethod("DoSomething", new System.Type[] { base1.GetType() });
    if (method) {
        method.Invoke(new object[] { base1 });
    }
    
    0 讨论(0)
  • 2021-02-20 05:53

    As @SLaks has already stated you cannot call the method as an extension method (even with a dynamic type) ... you can however call the static method with a dynamic type

    So, although this will fail

    Base base1 = new Child1();
    (base1 as dynamic).DoSomething();
    

    This will work

    Base base1 = new Child1();
    Extensions.DoSomething(base1 as dynamic);
    
    0 讨论(0)
提交回复
热议问题