2

我有一个基类(订单)和一组子类(产品订单、特殊订单、零件订单等)。

这些子类中只有一些实现了具有单个方法声明(object getcustdetails())的特定接口(ITrackingCustomer)。

作为我的解决方案的一部分,我所有的订单都在一个中心位置处理,即任何 crud 方法都通过一个中心层。在这个中心层中,我想做以下事情:

如果订单是 ITrackingCustomer 类型

然后调用方法 getcustdetails()

我使用以下代码进行此工作:

if (typeof(ITrackingCustomer).IsAssignableFrom(Order.GetType())) 
{ 
     MethodInfo theMethod = Order.GetType().GetMethod("getcustdetails"); 
     object y = theMethod.Invoke(Order, null); 
} 

我对使用 isassignablefrom 的第一部分感到满意​​,但想对第二部分使用性能强度较低的方法(即使用调用的反射)。

我的问题是:

有没有更有效的方法来做到这一点,因为我已经读到使用调用命令代价高昂。

4

4 回答 4

6
ITrackingCustomer ord = Order as ITrackingCustomer;
if (ord != null)
{
    object y = ord.getcustdetails();
}
于 2010-01-28T14:58:27.693 回答
1

你可以做:

if(Order is ITrackingCustomer) {
    ((ITrackingCustomer)Order).getcustdetails();
}
于 2010-01-28T14:58:08.290 回答
1

正如其他人所提到的,您可以使用isandas运算符来确定对象是否属于某种类型。然而,多态性通常更适合解决这类问题。

如果可行,也许您可​​以getcustdetails()Order. 如果virtual它具有合适的默认实现(即不返回详细信息或null),或者如果所有类型都必须实现它abstract是有意义的,则进行此操作。Order既然你有ITrackingCustomer接口,我怀疑一个abstract方法不能很好地工作。但是,对于Order实现 的类型ITrackingCustomer,您可以getcustdetails()相应地实现。

在这一点上,听起来您可以取消ITrackingCustomer,但如果不了解有关如何使用此接口的更多详细信息,我不能肯定地说。

完成此操作后,您将不需要执行任何类型检查,因为调用Order.getcustdetails()始终会分派到正确的具体实现。

于 2010-01-28T15:12:02.340 回答
0

如果您尝试按名称调用而不是在接口中调用成员,并且您希望能够调用相同的方法数千次,那么除了强制转换(我假设您不能这样做,因为您不这样做) t 知道类型)或反射是 JIT 编译调用。

Rick Strahl 有一篇关于调用方法的各种方式的性能成本的不错的博客文章,并且评论导致这篇文章展示了如何将委托拉出到非虚拟方法。

最后,我写了一篇关于如何动态构建适配器类的博客文章。你可以用它做一个满足抽象类的直接可调用对象:

public abstract class CustomerDetailsGetter {
    public abstract object getcustdetails();
}

// ...

AdapterCompiler compiler = new AdapterCompiler();
AdapterFactory<CusomterDetailsGetter> factory = compiler.DefineAdapter<CustomerDetailsGetter>(Order.GetType());

// now, my code assumes you want to construct an object from whole cloth
// but the code could be changed to invoke the default constructor and set the
// adapted object.

CustomerDetailsGetter getter = factory.Construct(null)

object info = getter.getcustdetails();

现在,我需要明确一点——这样做只有两个原因:

  1. 当您在编译时知道目标参数并且您不知道目标程序集并且您希望您的代码是干净的时,您希望能够具有按名称调用的语义。一个例子是知道它想要创建和使用特定对象的代码,但不知道程序集在运行时是否可用并且被禁止引用。

  2. 你想调用对象方法的反射,但想快速、快速、快速地调用它们数千或数百万次。

如果这是一个“调用一次”的事情,你最好编写一个辅助方法来做你想做的事。

于 2010-01-28T15:30:52.490 回答