我正在使用一个为我生成一堆类的库。
这些类都继承自公共基类,但该基类没有定义所有子类共有的几个方法。
例如:
SubClassA : BaseClass{
void Add(ItemA item) {...}
ItemA CreateNewItem() {...}
}
SubClassB: BaseClass{
void Add(ItemB item) {...}
ItemB CreateNewItem() {...}
}
不幸的是,基类没有这些方法。这会很棒:
BaseClass{
// these aren't actually here, I'm just showing what's missing:
abstract void Add(ItemBaseClass item); // not present!
abstract ItemBaseClass CreateNewItem(); // not present!
}
由于我的A + B对象有一个共同的基类,而Item对象有一个共同的基类,我原本希望从多态的奇妙世界中受益。
不幸的是,由于常用方法实际上并不存在于基类中,我无法虚拟地调用它们。例如,这将是完美的:
BaseClass Obj;
Obj = GetWorkUnit(); // could be SubClassA or SubClassB
ItemBaseClass Item = Obj.CreateNewItem(); // Compile Fail: CreateNewItem() isn't in the base class
Item.DoSomething();
Obj.Add(Item); // Compile Fail: Add(...) isn't in the base class
显然,施法可行,但后来我需要知道哪种类型可以否定好处。
如何“强制”调用这些方法?我并不担心得到一个没有实现我试图调用的方法的对象。我实际上可以在VB中做我想做的事情 - 我没有得到intellisense但是编译器很开心并且它有效:
CType(Obj, Object).Add(Item) // Note: I'm using C#--NOT VB
Againt,我无法控制这些类(我认为排除了部分类)。
答案 0 :(得分:6)
如果不使用反射或其他脏技巧,则无法调用派生类的非虚方法。如果你想这样做,那么很容易:
// obj is your object reference.
obj.GetType().InvokeMember("MethodName",
System.Reflection.BindingFlags.InvokeMethod, null, obj, null /* args */)
答案 1 :(得分:3)
我可能会遗漏一些东西,但为什么不从这些方法的界面中制作和继承呢?
如果您控制实例的创建过程,您可以通过继承您未编写的类来获得所需的内容,然后添加接口(无需编写代码,编译器将映射接口到现有的非虚方法。)
答案 2 :(得分:0)
答案 3 :(得分:0)
如果您使用的是Visual Studio 2008,则可以为基类创建扩展方法。在该扩展方法中,您将执行转换并调用子类的方法。这也应该适用于2.0框架目标项目,只要您使用VS 2008进行编译。借用其他建议的反射代码,您可以执行以下操作...
public static class MyExtensions
{
public static ItemBaseClass CreateNewItem(this BaseClass item)
{
return item.GetType().InvokeMember("MethodName", System.Reflection.BindingFlags.InvokeMethod, null, obj, null /* args */);
}
}
答案 4 :(得分:0)
另一种可能性是使用一些代理机制,例如RealProxy(在性能方面效率不是很高)或者通过使用动态创建的DynamicMethods更好,这样使用反射的开销只有每种类型支持一次,而保持它像反射方法一样灵活。当你需要多次调用该方法时,这会得到很大回报,但它需要一些MSIL知识。
答案 5 :(得分:0)
问题#1:你的子类没有覆盖任何东西 问题#2:您的子类具有与基类不同的函数签名
确保您的签名正确无误,如果您要覆盖它们,请将它们标记为虚拟而非抽象。如果您不希望它们执行任何操作,则必须向基类虚函数添加一个空体。
class ItemBase{}
class ItemA : ItemBase{}
class ItemB : ItemBase{}
class BaseClass
{
public virtual void Add(ItemBase item){}
public virtual ItemBase CreateItem() { return null; }
}
class ClassA : BaseClass
{
public override void Add(ItemBase item)
{
//do whatever
throw new NotImplementedException();
}
public ItemBase CreateItem()
{
//create an ItemBase and return
throw new NotImplementedException();
}
}
答案 6 :(得分:-1)
您忘记了子类的方法定义中的“override”关键字。当某些东西被声明为“抽象”时,它按照定义是虚拟的,因此在子类中,您需要将“override”关键字放在方法声明的前面。那么应该做些什么呢:
BaseClass{
abstract void Add(ItemBaseClass item); // not present!
abstract ItemBaseClass CreateNewItem(); // not present!
}
SubClassA : BaseClass{
override void Add(ItemA item) {...}
override ItemA CreateNewItem() {...}
}
SubClassB: BaseClass{
override void Add(ItemB item) {...}
override ItemB CreateNewItem() {...}
}
这应该在您的使用示例中完全按照您的意愿工作。