Внедрение зависимостей общего типа: Как ввести 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 также на левом сайте ... Так как я должен использовать c # 2.0, я не могу использовать волшебное слово "var", который очень помог бы в этом случае ... но как я могу сделать так, чтобы он был открытым и гибким ...


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

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

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

ChrystalReportHandler:IReportHandler<CrystalReportDocument>

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

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

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

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

10.12.2008 09:05:46
3 ОТВЕТА

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

Пытаться:

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

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

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


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

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

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

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

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

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

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

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

1
22.12.2008 22:41:39

Я думаю, что с вашим текущим дизайном вы создаете «зависимость» между 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 { }
2
10.12.2008 10:20:02

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

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

    container.AddComponent> (TypeOf (FooHandler));

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

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

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

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

1
22.12.2008 22:27:02