C# 无反射调用方法声明

C# 无反射调用方法声明,c#,reflection,methods,polymorphism,interface-implementation,C#,Reflection,Methods,Polymorphism,Interface Implementation,我有一个基类(order)和一组子类(productorder、speciallorder、partsorder等) 只有其中的一些子类实现了一个特定接口(ITrackingCustomer),该接口具有一个方法声明(object getcustdetails()) 作为我的解决方案的一部分,我的所有订单都在一个中心位置处理,即任何crud方法都通过一个中心层。在这个中心层中,我要执行以下操作: 如果订单类型为ITrackingCustomer 然后调用getcustdetails()方法 我使

我有一个基类(order)和一组子类(productorder、speciallorder、partsorder等)

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

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

如果订单类型为ITrackingCustomer

然后调用getcustdetails()方法

我使用以下代码完成此工作:

if (typeof(ITrackingCustomer).IsAssignableFrom(Order.GetType())) 
{ 
     MethodInfo theMethod = Order.GetType().GetMethod("getcustdetails"); 
     object y = theMethod.Invoke(Order, null); 
} 
我对第一部分使用isassignablefrom感到满意,但希望对第二部分使用性能要求较低的方法(即使用invoke的反射)

我的问题是:

有没有一种更有效的方法来实现这一点,正如我读到的那样,使用invoke命令代价高昂。

您可以这样做:

if(Order is ITrackingCustomer) {
    ((ITrackingCustomer)Order).getcustdetails();
}

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

如果可行,您可以在
Order
上放置
getcustdetails()
方法。如果它有合适的默认实现(即不返回详细信息或
null
),则将其设置为
virtual
;如果所有
Order
类型都必须实现,则将其设置为
abstract
。由于您有
ITrackingCustomer
界面,我怀疑
abstract
方法不会很好地工作。但是,对于实现
ITrackingCustomer
Order
类型,您可以相应地实现
getcustdetails()

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


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

如果您尝试按名称调用而不是调用接口中的成员,并且希望能够调用相同的方法数千次,然后,除了强制转换(我假设您不能这样做,因为您不知道类型)或反射之外,还需要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();
公共抽象类CustomerDetailsGetter{
公共抽象对象getcustdetails();
}
// ...
AdapterCompiler编译器=新AdapterCompiler();
AdapterFactory=compiler.DefineAdapter(Order.GetType());
//现在,我的代码假设您想要从整个布料构造一个对象
//但是可以更改代码以调用默认构造函数并设置
//适应对象。
CustomerDetailsGetter=factory.Construct(null)
对象信息=getter.getcustdetails();
现在,我需要澄清的是,这样做只有两个原因:

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

  • 您想将对象方法称为la反射,但要快速、快速、快速地执行此操作,并且将调用它们数千次或数百万次


  • 如果是“一次调用”,那么最好编写一个helper方法来做您想做的事情。

    是的,我同意。这是一个更好的选择。我写得很快,没有考虑太多:)嗨,谢谢你的回复,yeh u geussed right我不能使用虚拟方法,因为基类是由wcfria生成的代码,因此是接口。虽然我可能应该提到,但干杯。嗨,泰汉克斯的回应,虽然这不完全是我在这里寻找的,但看看你的博客,这将在项目的其他领域肯定是有用的。谢谢
    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();