Внедрение зависимостей общего типа: Как ввести T - PullRequest
4 голосов
/ 10 декабря 2008

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

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 на левом сайте ... Так как я должен использовать c # 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) 

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

Ответы [ 3 ]

2 голосов
/ 10 декабря 2008

Я думаю, что с вашим текущим дизайном вы создаете «зависимость» между 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 { }
1 голос
/ 23 декабря 2008

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

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

    container.AddComponent> (TypeOf (FooHandler));

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

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

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

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

1 голос
/ 10 декабря 2008

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

Попытка:

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

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

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


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

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

Теперь уточним.

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

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

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

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

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

...