Фон
У меня есть проект, который зависит от использования определенного типа аппаратного устройства, хотя на самом деле не имеет значения, кто делает это аппаратное устройство, если оно делает то, что мне нужно. При этом даже два устройства, которые должны делать одно и то же, будут иметь различия, если они не сделаны одним и тем же производителем. Поэтому я думаю использовать интерфейс, чтобы отделить приложение от конкретной марки / модели используемого устройства, и вместо этого иметь интерфейс, охватывающий только функциональность самого высокого уровня. Вот как я думаю, что моя архитектура будет выглядеть так:
- Определите интерфейс в одном проекте C #
IDevice
. - Имейте конкретику в библиотеке, определенной в другом проекте C #, который будет использоваться для представления устройства.
- Попросите конкретное устройство реализовать
IDevice
интерфейс. IDevice
Интерфейс может иметь такие методы , какGetMeasurement
илиSetRange
.- Заставьте приложение иметь знания о бетоне и передайте бетон к коду приложения, которое использует (а не реализует )
IDevice
устройство.
Я уверен, что это правильный путь, потому что тогда я смогу изменить, какое устройство используется, не влияя на приложение (что иногда случается). Другими словами, не имеет значения, как реализации GetMeasurement
или SetRange
фактически работают через бетон (как могут отличаться у производителей устройства).
Единственное сомнение, на мой взгляд, заключается в том, что теперь и приложение, и конкретный класс устройства зависят от библиотеки, содержащей IDevice
интерфейс. Но разве это плохо?
Я также не вижу, как приложению не нужно будет знать об устройстве, если оно не IDevice
находится в одном пространстве имен.
Вопрос
Кажется ли это правильным подходом для реализации интерфейса, позволяющего отделить зависимость между моим приложением и устройством, которое оно использует?
Ответы:
Я думаю, у вас есть довольно хорошее понимание того, как работает отделенное программное обеспечение :)
Это не должно быть!
Вы можете справиться со всеми этими проблемами с помощью структуры проекта .
Как я обычно делаю это:
Common
проект. Нечто подобноеMyBiz.Project.Common
. Другие проекты могут ссылаться на него, но он не может ссылаться на другие проекты.MyBiz.Project.Devices.TemperatureSensors
. Этот проект будет ссылаться наCommon
проект.Client
проект, который является точкой входа в мое приложение (что-то вродеMyBiz.Project.Desktop
). При запуске приложение проходит процесс начальной загрузки, где я настраиваю сопоставления абстракции и конкретной реализации. Я могу создать экземпляр моего бетона ,IDevices
какWaterTemperatureSensor
иIRCameraTemperatureSensor
здесь, или я могу настроить услуги , как Фабрики или контейнер IoC позже инстанцировать нужные типов конкретных для меня.Ключевым моментом здесь является то, что только ваш
Client
проект должен знать как абстрактныйCommon
проект, так и все конкретные проекты реализации. Ограничивая абстрактное-> конкретное отображение вашим кодом Bootstrap, вы позволяете остальной части вашего приложения блаженно не знать о конкретных типах.Слабо связанный код ftw :)
источник
new Foo(new DeviceA());
), вместо того, чтобы иметь личное поле в Foo для создания экземпляра DeviceA (private IDevice idevice = new DeviceA();
) - вы все равно получаете DI, так как Foo не знает о DeviceA в первом случаеДа, это похоже на правильный подход. Нет, для приложения и библиотеки устройств неплохо зависеть от интерфейса, особенно если вы контролируете реализацию.
Если вы обеспокоены тем, что устройства могут не всегда реализовывать интерфейс, по какой-либо причине вы можете использовать шаблон адаптера и адаптировать конкретную реализацию устройств к интерфейсу.
РЕДАКТИРОВАТЬ
При решении вашей пятой задачи, подумайте о такой структуре (я предполагаю, что вы управляете определением своих устройств):
У вас есть основная библиотека. В нем есть интерфейс под названием IDevice.
В вашей библиотеке устройств у вас есть ссылка на вашу базовую библиотеку, и вы определили ряд устройств, которые все реализуют IDevice. У вас также есть фабрика, которая знает, как создавать различные виды IDevices.
В вашем приложении вы включаете ссылки на основную библиотеку и библиотеку устройств. Ваше приложение теперь использует фабрику для создания экземпляров объектов, которые соответствуют интерфейсу IDevice.
Это один из многих возможных способов решения ваших проблем.
ПРИМЕРЫ:
источник
Вам нужно подумать об обратном. Если вы не пойдете по этому пути, приложение должно будет знать обо всех различных устройствах / реализациях. Следует помнить, что изменение этого интерфейса может привести к поломке вашего приложения, если оно уже вышло из-под контроля, поэтому вы должны тщательно разработать этот интерфейс.
Просто да
Приложение может загрузить конкретную сборку (dll) во время выполнения. См .: /programming/465488/can-i-load-a-net-assembly-at-runtime-and-instantiate-a-type-knowing-only-the-na
Если вам нужно динамически выгрузить / загрузить такой «драйвер», вам нужно загрузить сборку в отдельный домен приложений .
источник
IDevice
интерфейс, чтобы его устройство можно было использовать с вашим приложением, тогда не было бы другого способа IMO.