Arhn - архитектура программирования

Внедрение зависимости универсального типа: как внедрить T

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

public interface IDocHandler<T>where T: class
{

T Document { get;set;}

void Load(T doc);

void Load(string PathToDoc);

void Execute();

void Execute(T doc);

}

И для разных типов документов реализую этот интерфейс.

Например:

public class FinanceDocumentProcessor:IDocumentHandler<ReportDocument>
{} 


public class MarketingDocumentProcessor:IDocumentHandler<MediaDocument>
{} 

Тогда я могу сделать, конечно, что-то вроде этого:

IDocumentHandler<ReportDocument> docProc= new FinanceDocumentProcessor();

Было бы интересно узнать, как я могу внедрить T во время выполнения, чтобы сделать строку выше слабо связанной...

IDocumentHandler<ReportDocument> docProc = container.resolve("FinanceDocumentProcessor());

но я хочу решить для каждой конфигурации, хочу ли я иметь свой FinanceDomcumentProcessor или мой MarketingDocumentProcessor... поэтому мне также придется вводить T на левом сайте... Поскольку я должен использовать С# 2.0, я не могу использовать волшебное слово "var", что очень помогло бы в этом случае... но как я могу сделать его открытым и гибким...


Извините за недопонимание и спасибо за все комментарии, но у меня есть еще один пример для моей задачи (возможно, я использую для этого неправильный дизайн) ... Но я попробую: та же ситуация, но другое объяснение

Пример изображения у меня есть:

ReportingService, Crystal, ListAndLabel Три разных типа отчетных документов. У меня есть общий обработчик IReportHandler<T> (будет таким же, как указано выше), этот обработчик предоставляет все функции для обработки документа отчета. Например

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

Теперь я хочу использовать фреймворк, такой как Unity (или какой-то другой фреймворк), для внедрения зависимостей, чтобы через конфигурацию решить, хочу ли я использовать Crystal, Reportingservices или List and Label.

Когда я указываю свое сопоставление, я могу ввести свой ChrystalReportHandler, но как я могу ввести T слева или, лучше сказать, тип ReportDocument.

IReportHandler<T (this needs also to be injected)> = IOContainer.Resolve(MyMappedType here) 

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


Ответы:


1

Я думаю, что с вашим текущим дизайном вы создаете «зависимость» между IDocumentHandler и конкретным документом (ReportDocument или MediaDocument), поэтому, если вы хотите использовать IDocumentHandler<ReportDocument or MediaDocument> непосредственно в своем коде, вы должны предположить, что ваш контейнер даст вам именно это. В этом случае контейнер не должен нести ответственность за разрешение типа документа.

Хотели бы вы изменить свой дизайн таким образом?

public interface IDocumentHandler
{
    IDocument Document { get; set; }

    void Load(IDocument doc);

    void Load(string PathToDoc);

    void Execute();

    void Execute(IDocument doc);

}

public class IDocument { }
public class ReportDocument : IDocument { }
public class MediaDocument : IDocument { }
public class FinanceDocumentProcessor : IDocumentHandler { }
public class MarketingDocumentProcessor : IDocumentHandler { }
10.12.2008

2

Если я вас правильно понял, у вас есть два варианта.

  1. если у вас есть интерфейс IDocHandler и несколько классов, реализующих его, вы должны явно зарегистрировать каждый тип, например:

    container.AddComponent>(typeof(FooHandler));

  2. если у вас есть один класс DocHandler, вы можете зарегистрироваться с помощью компонента, используя открытый универсальный тип

    container.AddComponent(typeof(IDocHandler‹>), typeof(DocHandler‹>));

то каждый раз, когда вы разрешаете IDocHandler, вы получаете экземпляр DocHandler, а когда вы разрешаете IDocHandler, вы получаете DocHandler.

надеюсь, это поможет

22.12.2008

3

Вам нужно использовать нестандартный интерфейс с левой стороны.

Пытаться:

public interface IDocumentHandler { }
public interface IDocumentHandler<T> : IDocumentHandler { }

Это создаст два интерфейса. Все общее, не относящееся к T поместите в базовый интерфейс, а все остальное в общий.

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


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

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

Теперь, чтобы уточнить.

Вы не можете вводить что-либо «с левой стороны». Это невозможно. Этот код должен компилироваться, быть правильным и быть на 100% «там» во время компиляции. Вы не можете сказать «мы расскажем вам, что такое T во время выполнения» для этой части. Это просто невозможно.

Так что единственное, что вам остается, это вообще убрать букву Т. Сделайте так, чтобы код, использующий зависимость, вообще не зависел от T. Или, по крайней мере, используйте рефлексию, чтобы узнать, что такое T, и делайте что-то, основываясь на этом знании.

Это все, что вы можете сделать. Вы не можете заставить код с левой стороны изменяться в зависимости от того, что вы возвращаете из метода с правой стороны.

Это невозможно.

Отсюда мой ответ.

10.12.2008
Новые материалы

Коллекции публикаций по глубокому обучению
Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

Представляем: Pepita
Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

Советы по коду Laravel #2
1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

3 способа решить квадратное уравнение (3-й мой любимый) -
1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

Создание VR-миров с A-Frame
Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

Демистификация рекурсии
КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..