2016-05-18 3 views
1

У меня есть Unity DI в проекте, который вызывает тесты модуляции регистрации зависимостей. Я думаю, это потому, что у меня синтаксис неправильный для регистрации дженериков. Полагаю, это может быть нечто другое, чего я не вижу. В любом случае, я попытался выполнить [эту статью] [1], чтобы зарегистрировать дженерики, но я счел это недостающим и запутанным, поэтому я до сих пор не получил его. Он упоминает классы Unity, такие как InjectionConstructor и GenericaParameter, но пытаясь использовать их, я получаю различные ошибки времени компиляции. Я тоже не нахожу ничего здесь, чтобы разобраться. Я надеюсь, что у кого-то здесь может быть более четкое объяснение того, как регистрировать эти вещи (или какой-то другой ответ, если это не проблема).Регистрация дженериков в единстве

Вот некоторые соответствующий код:

Первый мой главный интерфейс уровня, который будет введен в и используется код клиента, указав тип для Т.

namespace Elided.Extraction.Interfaces 
{ 
    public interface IDataExtractionService<out T> 
    { 
     T GetData(Stream stream); 
    } 
} 

Следующий класс является реализация который имеет инъекционный IDataExtractor:

namespace Elided.Extraction 
{ 
    public class DataExtractionService<T> : IDataExtractionService<T> 
    { 
     private readonly IDataExtractor<T> extractor; 

     internal DataExtractionService(IDataExtractor<T> extractor) 
     { 
      this.extractor = extractor; 
     } 

     public T GetData(Stream workbookStream) 
     { 
      // elided 
      return this.extractor.GetData(elidedArgument) 
     } 
    } 
} 

А вот интерфейс для IDataExtractor:

namespace Elided.Extraction.Behaviors.Interfaces 
{ 
    internal interface IDataExtractor<out T> 
    { 
     T GetData(object elidedArgument); 
    } 
} 

Вот реализация IDataExtractor. Это реализация типа DataSet, но идея состоит в том, что могут существовать многочисленные реализации, позволяющие клиентскому коду иметь инъекционную систему IDataExtractionService или любой другой тип, для которого написана реализация экстрактора.

namespace Elided.Extraction.Behaviors 
{ 
    internal class DataSetExtractor : IDataExtractor<DataSet> 
    { 
     public DataSet GetData(object elidedArgument) 
     { 
      // implementation elided 
      // returns a DataSet 
     } 
    } 
} 

И, наконец, вот мой регистрационный код (в той же сборке, что и выше материал), который я не верю, что работает:

public void RegisterDependencies(IDependencyContainer container) 
{ 
    container.RegisterType(typeof(IDataExtractionService<>), typeof(DataExtractionService<>)); 
    container.RegisterType(typeof(IDataExtractor<DataSet>), typeof(DataSetExtractor)); 
} 

Update: Конкретное сообщение об ошибке поступает из Исключение броска единичным тестом:

Исключение произошло, когда: при разрешении. Исключение составляет: InvalidOperationException - тип DataExtractionService`1 не может быть сконструирован. Вы должны сконфигурировать контейнер для подачи этого значения . [1]: https://msdn.microsoft.com/en-us/library/ff660936(v=pandp.20).aspx

+0

В чем проблема? У вас ошибка компиляции? На какой линии? Или у вас есть исключение во время выполнения? Что это, если так? –

+0

@YacoubMassad - мой модульный тест завершается с ошибкой и показывает следующее сообщение об исключении: Исключение произошло во время: при разрешении. Исключение: InvalidOperationException. Тип ExcelDataExtractionService'1 не может быть сконструирован. Вы должны настроить контейнер для подачи этого значения. – bubbleking

+0

У вас есть 'IDataExtractionService <>', настроенный для любого типа общего типа. Но единственная регистрация для 'IDataExtractor ' предназначена для 'IDataExtractor '. Таким образом, вы не можете разрешить 'IDataExtractionService <>' для чего угодно * кроме * 'IDataExtractionService '. В противном случае любой тип общего типа, который вы используете для 'IDataExtractionService <>', понадобится соответствующему 'IDataExtractor <>', но единственный для 'DataSet'. –

ответ

1

я вставил свой код и создал тестовый блок:

[TestMethod] 
    public void TestUnityConfiguration() 
    { 
     var container = new UnityContainer(); 

     //This part is copied from your Unity configuration. 
     container.RegisterType(typeof(IDataExtractionService<>), typeof(DataExtractionService<>)); 
     container.RegisterType(typeof(IDataExtractor<DataSet>), typeof(DataSetExtractor)); 
     var x = container.Resolve<IDataExtractionService<DataSet>>(); 
     Assert.IsInstanceOfType(x, typeof(DataExtractionService<DataSet>)); 
     var y = container.Resolve<IDataExtractor<DataSet>>(); 
     Assert.IsInstanceOfType(y, typeof(DataSetExtractor)); 
    } 

Первая не удалась, поскольку DataExtractionService не имеет открытый конструктор, так что Unity не может создать его ,

Я пробовал записи в AssemblyInfo.cs, чтобы сделать внутренности видимыми для Unity, но это не сработало.

Я еще прочитал - для скрытых конструкторов не существует обходного пути. См. this post.

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

+0

Мне удалось получить эту работу, сделав эти основные части общедоступными, о чем я не волнуюсь. Я должен решить, хочу ли я держать DI и публиковать эти части, или, на определенной глубине в цепочке, идти бетонно и держать вещи внутренними. – bubbleking

+0

Собственно, я неправильно понял. Мне удалось оставить внутренние классы и просто настроить конструктор на публичные. Это позаботилось об этом и спрятало детали сборки на нижнем уровне! – bubbleking

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