6

У меня есть помощник тега с несколькими конструкторами в моем приложении ASP.NET 5. Это приводит следующее сообщение об ошибке во время выполнения, когда ASP.NET 5 пытается разрешить тип:ASP.NET 5 MVC 6 Инъекция зависимостей с несколькими конструкторами

InvalidOperationException: Множественные конструкторы, принимающим всем указанным типам аргументов были найдены в типе "MyNameSpace.MyTagHelper. Должен быть только один применимый конструктор.

Один из конструкторов является без параметров, а другой имеет некоторые аргументы, параметры которых не являются зарегистрированными. Я хотел бы использовать конструктор без параметров.

Есть ли какой-то способ заставить инфраструктуру внедрения зависимостей ASP.NET 5 выбрать конкретный конструктор? Обычно это делается с помощью атрибута, но я ничего не могу найти.

Моим вариантом использования является то, что я пытаюсь создать один класс, который является как TagHelper, так и HTML-помощником, что вполне возможно, если эта проблема будет решена.

+4

Ваши инъекционные продукты должны иметь только один конструктор. Наличие [нескольких конструкторов является анти-шаблоном] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97). – Steven

+0

Да, это не идеально. Я придумаю обход. –

+0

Если вы полностью прочитали [статью] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97), вы увидите, что ответ прост. В случае типа, которым вы управляете: удалите один конструктор. Если этот «MyTagHelper» является сторонним или фрейм-типом, зарегистрируйте его с помощью делегата фабрики и вызовите конкретный конструктор внутри этого делегата. – Steven

ответ

9

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

services.AddScoped<IService>(provider => { 
    var dependency = provider.GetRequiredService<IDependency>(); 

    // You can select the constructor you want here. 
    return new Service(dependency, "my string parameter"); 
}); 
+0

Спасибо, это полезно для подключения сторонних библиотек, которые я не контролирую. – SimonGates

1

ASP.NET ядро ​​1,0 ответа

других ответов по-прежнему верно для PARAMET er-less, т. е. если у вас есть класс с конструктором без параметров и конструктором с аргументами, исключение в вопросе будет выбрано.

Если у вас есть два конструктора с аргументами, поведение заключается в использовании первого конструктора соответствия, в котором известны параметры. Вы можете посмотреть исходный код для класса ConstructorMatcher для получения более подробной информации here.

0

ASP.NET Ядро Ответ

Я закончил с следующим обходным, пока они не исправить/улучшить это.

Во-первых, объявите только одного конструктора в своем контроллере (передавая только нужные параметры конфигурации), учитывая, что объекты настроек, переданные в конструкторе, могут быть пустыми (.NET Core будет автоматически вводить их, если вы настроите их в методе Startup):

public class MyController : Controller 
{ 
    public IDependencyService Service { get; set; } 

    public MyController(IOptions<MySettings> settings) 
    { 
     if (settings!= null && settings.Value != null) 
     { 
      Service = new DependencyServiceImpl(settings.Value); 
     } 
    } 
} 

Затем, в своих методах испытаний вы можете создать экземпляр контроллера двумя способами:

  1. оскорбляющих возражают IOptions, когда вы строите тестируемый объект
  2. Постройте передачу null во всех параметрах, а затем залейте зависимость, которую вы будете использовать в своих тестах.После у вас есть пример:
[TestClass] 
    public class MyControllerTests 
    { 
     Service.Controllers.MyController controller; 
     Mock<IDependencyService> _serviceStub; 

     [TestInitialize] 
     public void Initialize() 
     { 
      _serviceStub = new Mock<IDependencyService>(); 
      controller = new Service.Controllers.MyController(null); 
      controller.Service = _serviceStub.Object; 
     } 
    } 

С этого момента вы можете иметь полное тестирование с инъекции зависимостей и насмешливый готов в .NET Core.

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

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