2

У меня есть базовый класс (заказ) с набором подклассов (товарный блок, специальный заказ, раздел и т. Д.).вызов метода декларации без отражения

Только некоторые из этих подклассов реализуют определенный интерфейс (ITrackingCustomer), который имеет одно объявление метода (объект getcustdetails()).

В качестве части моего решения все мои заказы обрабатываются в центральном месте, то есть любые методы crud проходят через центральный слой. В этом центральном слое я хочу сделать следующее:

Если заказ типа ITrackingCustomer

Затем метод Invoke getcustdetails()

я эту работу, используя следующий код:

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

Я доволен первой частью, использующей isassignablefrom, но хотел бы использовать менее интенсивный метод для s третья часть (т.е. отражение с использованием invoke).

Мой вопрос:

Есть ли более эффективный способ сделать это, как я прочитал, что с помощью команды Invoke является дорогостоящим.

ответ

1

Вы можете сделать:

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

Всегда предпочитайте 'как' в этом случае ... –

+0

Да, я согласен. Это лучший вариант. Я написал быстро, не задумываясь: –

6
ITrackingCustomer ord = Order as ITrackingCustomer; 
if (ord != null) 
{ 
    object y = ord.getcustdetails(); 
} 
1

Как уже упоминалось, вы можете использовать is и as операторы, чтобы определить, является ли объект определенного типа. Однако полиморфизм обычно лучше подходит для решения этой проблемы.

Если это возможно, возможно, вы можете разместить метод getcustdetails() на Order. Сделайте это virtual, если он имеет подходящую реализацию по умолчанию (т. Е. Не возвращает никаких данных или null), или abstract, если имеет смысл, что все типы Order должны реализовать его. Поскольку у вас есть интерфейс ITrackingCustomer, я подозреваю, что метод abstract не будет работать. Однако для Order типов, которые реализуют ITrackingCustomer, вы можете затем реализовать getcustdetails().

На данный момент это звучит так, как будто вы можете покончить с ITrackingCustomer, но я не могу сказать наверняка, не зная подробностей о том, как этот интерфейс используется.

Как только это будет сделано, вам не нужно будет выполнять какие-либо проверки типа, так как вызов Order.getcustdetails() всегда отправляет правильную конкретную реализацию.

+0

Привет, спасибо за ответ, yeh u geussed right Я не могу использовать виртуальные методы, поскольку базовый класс - это код, созданный wcfria и, следовательно, интерфейс. Привет, хотя я, наверное, должен был упомянуть. – steve

0

Если вы пытаетесь выполнить вызов по имени вместо вызова члена в интерфейсе, и вы хотите иметь возможность вызывать один и тот же метод тысячи раз, а затем отличать от него (который, как я полагаю, вы не можете сделать потому что вы не знаете тип), или отражение - это JIT-компиляция вызова.

Rick Strahl имеет a nice blog article on стоимость исполнения различных способов вызова метода и комментариев приводит к this article, который показывает, как вывести делегат на не виртуальный метод.

И наконец, я написал a blog article on how to build adapter classes on the fly. Что вы можете сделать с этим, делают непосредственно вызываемый объект, который отвечает абстрактный класс:

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. вам хотите иметь возможность иметь семантику по имени, когда вы знаете целевые аргументы во время компиляции, и вы не знаете, есть ли целевая сборка, и вы хотите, чтобы ваш код был CLEAN. Примером этого является код, который знает, что он хочет создать и использовать конкретный объект, но не знает, будет ли сборка доступна до запуска, и ей запрещено иметь ссылку.

  2. Вы хотите вызвать методы объекта a la reflection, но хотите сделать это быстро, быстро, быстро и будете называть их тысячи или миллионы раз.

Если это вопрос «один раз», вам лучше написать вспомогательный метод, чтобы делать то, что вы хотите.

+0

Привет, Tyhanks для ответа, в то время как это не совсем то, что я ищу здесь, глядя на ваш блог, это определенно будет полезно в других областях проекта. Спасибо .... – steve

Смежные вопросы