我最近在编写代码时遇到过这个问题。有没有办法我们可以在基类中编写代码,以便根据类型识别正确的扩展方法?
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();
}
}
}
答案 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;
}
}