如何获得泛型类方法的正确扩展方法?

时间:2014-09-11 20:45:41

标签: c# generics inheritance extension-methods

我最近在编写代码时遇到过这个问题。有没有办法我们可以在基类中编写代码,以便根据类型识别正确的扩展方法?

namespace GenericsInheritance
{
    public class Animal { }

    public class Dinasaur : Animal { }

    public class Dragon : Animal { }

    public abstract class Zoo<T> where T : Animal
    {
        public virtual string IdentifyYourSelf(T record)
        {
            //Calling extension method
            string name = record.IdentifyYourSelf();
            return name;
        }
    }

    public class DinasaurZoo : Zoo<Dinasaur> 
    {
        //I could use this, just wanted to try if base class method does identify the correct extension method for the type.
        //public override string IdentifyYourSelf(Dinasaur record)
        //{
        //    return record.IdentifyYourSelf();
        //}
    }

    public class DragonZoo : Zoo<Dragon> { }

    public class AnimalZoo : Zoo<Animal> { }

    //Extensions methods class.
    public static class LieDetector
    {
        public static string IdentifyYourSelf(this Animal record) { return "Animal"; }

        public static string IdentifyYourSelf(this Dinasaur record) { return "Dinasaur"; }

        public static string IdentifyYourSelf(this Dragon dog) { return "Dragon"; }

        //It works if I use this.
        //public static string IdentifyYourSelf<T>(this T record) where T : Animal
        //{            
        //    if (record is Dinasaur) { var dinasaur = record as Dinasaur; return IdentifyYourSelf(dinasaur); }
        //    else if (record is Dragon) { var dragon = record as Dragon; return IdentifyYourSelf(dragon); }        
        //    else return "I do not exist";
        //}
    }

    public class FbiInterrogation
    {
        public static void Main(string[] args)
        {
            var animal = new Animal();
            var dinasaur = new Dinasaur();
            var dragon = new Dragon();
            var dinasaurZoo = new DinasaurZoo();
            var dragonZoo = new DragonZoo();
            var animalZoo = new AnimalZoo();

            string name = dinasaurZoo.IdentifyYourSelf(dinasaur); //Prints Animal expecting Dinasaur
            name = dragonZoo.IdentifyYourSelf(dragon); //Prints Animal expecting Dragon
            name = animalZoo.IdentifyYourSelf(animal); //Prints Animal

            Console.ReadKey();
        }
    }
}

2 个答案:

答案 0 :(得分:2)

扩展方法根据调用它们的变量的静态类型来解析,而不是运行时类型。因此,您的问题的答案是“不” - 您必须通过派生类中的覆盖或通过繁琐的类型检查来执行此操作,如您在问题中指出的那样。

答案 1 :(得分:0)

这实际上可以通过反思实现,但我不确定这样做是否最好:

public abstract class Zoo<T> where T : Animal
{
    public virtual string IdentifyYourSelf(T record)
    {
        return typeof(LieDetector).GetMethod("IdentifyYourSelf", new[] {typeof(T)}, null).Invoke(record, new object[] {record}) as string;
    }
}