2008-10-26 3 views
11

В моем приложении используются измерительные приборы, подключенные к ПК. Я хочу, чтобы можно было использовать аналогичные инструменты у разных поставщиков.Определите метод интерфейса, который принимает разные параметры

Так я определил интерфейс:

interface IMeasurementInterface 
    { 
     void Initialize(); 
     void Close(); 
    } 

До сих пор так хорошо. Перед измерением мне нужно настроить прибор, и это означает, что для разных приборов очень разные параметры. Поэтому я хочу, чтобы определить метод, который принимает параметры, которые могут иметь различные структуры:

interface IMeasurementInterface 
{ 
    void Initialize(); 
    void Close(); 
    void Setup(object Parameters); 
} 

Я тогда бросить объект к тому, что мне нужно. Это путь?

+0

Планируете ли вы тестировать отдельные классы конкретных приборов или используете симуляторы и аппаратную разметку? – Kasper 2008-10-26 17:58:28

+0

Я буду использовать модульные тесты – Enrico 2008-10-26 18:58:53

ответ

0

Это, вероятно, будет работать. Другой вариант - передать параметры в словаре.

13

Возможно, вам лучше придумать абстрактный класс «Параметры», который расширяется каждым из разных параметров инструментов ... например. а затем с помощью Generics, чтобы гарантировать, что правильные параметры передаются правильные классы ...

public interface IMeasurement<PARAMTYPE> where PARAMTYPE : Parameters 
{ 
    void Init(); 
    void Close(); 
    void Setup(PARAMTYPE p); 
} 

public abstract class Parameters 
{ 

} 

А затем для каждого конкретного устройства,

public class DeviceOne : IMeasurement<ParametersForDeviceOne> 
{ 
    public void Init() { } 
    public void Close() { } 
    public void Setup(ParametersForDeviceOne p) { } 
} 

public class ParametersForDeviceOne : Parameters 
{ 

} 
+0

Параметры должны быть интерфейсом, нет? Я предпочитаю описание «Конфигурация» в отличие от установки. – Egwor 2008-10-26 16:59:10

2

Для меня это звучит как и Factory шаблон может быть полезно, особенно если вы собираетесь тестировать ваше приложение.

1

Если вы собираетесь иметь дело с еще более чем одного типа устройства, то контроллер + интерфейс устройства Разделения, который обменивается данными с помощью пары Имя vlaue будет хорошим решением

Развязка

иСПользоВание значение имени пар позволяет отделить код в устройство + контроллер + кода приложения структуры

Пример кода

class DeviceInterface 
    { 
    void Initialize(IController & Controller); 
    void Close(); 
    bool ChangeParameter(const string & Name, const string & Value); 
    bool GetParam(string & Name, string &Value); 
    } 

Каждая реализация устройства, при его создании должно быть создано с идентификацией контроллера, который может принимать свои команды и перевести их в реальное устройство команды

interface IController 
    { 
    Initialize(DeviceSpecific & Params); 
    Close(); 
    bool ChangeParameter(string & Name, string & Value); 
    bool ChangeParams(string & Name[], string &Value []); 
    } 

Ваш код пользователь будет выглядеть как этот

IController  objController = new MeasurementDevice(MeasureParram); 

DeviceInterface MeasureDevice = new DeviceInterface(objController); 

string Value; 

MeasureDevice.GetParam("Temperature", Value); 

if (ConvertStringToInt(Value) > 80) 
    { 
    MeasureDevice.ChangeParameter("Shutdown", "True"); 
    RaiseAlert(); 
    } 

Все, что должен сделать класс DeviceInterface, это позаботиться о передаче команд контроллеру. Контроллер должен следить за коммуникацией устройства.

Преимущества интерфейса Разделение

Защита Побейте изменения

Этого вида развязки позволит изолировать код приложения от контроллера.Изменения в устройстве не влияют на ваш код пользователя

ремонтопригодности Appliction Код

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

простота реализации

Вы также можете отделиться различные реализации контроллера в свои собственные проекты. Кроме того, ваше приложение может также настраивать команды и ответы более динамично, используя файлы XML и т. Д., Которые могут поставляться вместе с классами контроллеров, чтобы все ваше приложение стало более динамичным по своей природе.

Real Life

Один из последних проектов контроллеров производства от лидера в этой области работает таким же образом. Но они используют LON для связи с устройством.

LON?

протокол LON используется в контроллерах (думаю кондиционер/котел/вентиляторы и т.д.) сети используют эту концепцию, чтобы поговорить с различными устройствами

Таким образом, все, что вам нужно будет иметь это единый интерфейс, который может говорить с ваше устройство, а затем отправляет ему пару значений имени, используя LON. использование стандартного протокола также позволит вам разговаривать с другими устройствами, кроме вашего измерительного прибора. Существуют версии с открытым исходным кодом LON, если ваше устройство использует LON.

Если ваше устройство не поддерживает LON, вам может потребоваться создать что-то, где код пользователя по-прежнему работает с парами значений имени, а противоположный интерфейс преобразует ваши пары значений имени в эквивалент, соответствующий cotroller struct +, и связывается с устройством индикации в как понимает устройство.

Надеюсь, это пригодится.

1

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

public interface IMeasurementInterface 
{ 
    void Initialize(); 
    void Close(); 
    void Setup(IConfigurer config); 
} 

public interface IConfigurer 
{ 
    void ApplyTo(object obj); 
} 

public abstract ConfigurerBase<T> : IConfigurer where T : IMeasurementInterface 
{ 
    protected abstract void ApplyTo(T item); 

    void IConfigurator.ApplyTo(object obj) 
    { 
    var item = obj as T; 
    if(item == null) 
     throw new InvalidOperationException("Configurer can't be applied to this type"); 
    ApplyTo(item); 
    } 
} 

Таким образом, вы не портя вашу иерархию классов измерений (или не предоставляя реализации и при условии, что все реализации будут делать то, что вы хотите в любом случае). Это также означает, что вы можете протестировать свой код установки, перейдя в поддельное (или Mocked) устройство измерения.

Если процесс настройки должен управлять частными или защищенными данными, вы можете сделать конкретную реализацию IConfigurer находящейся внутри соответствующего класса Measurement.

1

У меня есть это для моего программного обеспечения, поскольку мне нужно поддерживать множество различных типов контроллеров движения для металлорежущих станков.

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

Как я сделать это следующим образом

interface IMeasurementInterface 
{ 
    void Initialize(); 
    void Close(); 
    void Setup(); 
    void Read (FileReader as <whatever read file object you are using>) 
    void Store (FileReader as <whatever read file object you are using>) 
    string Name(); 
} 

Setup вызывает диалоговое окно, созданного в сборке IMeasurementDevice. Диалоговое окно НЕ видимо вне сборки.

Теперь я знаю, что некоторые объектно-ориентированные или пуристы MVC могут возражать против этого. Однако я чувствую, что концепция скрытия внутренних элементов определенного класса измерений превосходит строгое соблюдение архитектуры MVC.

Моя общая философия заключается в том, что треугольный диалог реализован в той же сборке, при условии, что он является приватным для сборки и вызван объектом, реализующим на стандартных интерфейсах, которые я настраиваю. Опять же, причина этого заключается в том, что я считаю, что скрытие внутренних компонентов более ценно, чем попытка реализовать все диалоги в сборке верхнего уровня.

Указав метод чтения и метод Store, вы устраняете необходимость раскрывать внутренние параметры настройки для сохранения. Все, что вам нужно, это передать любой тип хранилища файлов, который вы используете, чтобы сохранить параметры настройки.

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

Как я это делаю, мой заводский класс получает список контроллеров движения. Этот список является частью мастер-класса, в котором хранятся все классы установки. Когда я читаю мои установочные файлы, я получаю используемые на самом деле контроллеры. Я извлекаю эти классы из списка и размещаю их в другом списке, который фактически используется во время процесса резки.

Причина, по которой я делаю это, заключается в том, что, когда пользователь настраивает контроллеры движения, ему необходимо выбрать из списка ВСЕХ доступных элементов управления, чтобы сообщить программному обеспечению, которое у него есть. Я считаю, что он более отзывчив, чтобы хранить список доступных контроллеров.

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