6

Mam pomocnika znacznika z wieloma konstruktorami w mojej aplikacji ASP.NET 5. To powoduje następujący błąd przy starcie, gdy ASP.NET 5 próbuje rozwiązać typ:ASP.NET 5 MVC 6 Injection Dependency Injection z wieloma konstruktorami

InvalidOperationException: Wiele konstruktorzy akceptując wszystkie podane typy argumentów zostały znalezione w rodzaju „MyNameSpace.MyTagHelper”. Powinien być tylko jeden odpowiedni konstruktor.

Jeden z konstruktorów jest bez parametrów, a drugi ma kilka argumentów, których parametry nie są typami zarejestrowanymi. Chciałbym użyć konstruktora bez parametrów.

Czy jest jakiś sposób uzyskania schematu wtrysku zależności ASP.NET 5 w celu wybrania konkretnego konstruktora? Zwykle odbywa się to za pomocą atrybutu, ale nie mogę znaleźć niczego.

Moim przypadkiem użycia jest to, że próbuję utworzyć pojedynczą klasę, która jest jednocześnie TagHelper, a także pomocnik HTML, który jest całkowicie możliwy, jeśli problem zostanie rozwiązany.

+4

Twoje strzykawki powinny mieć tylko jednego konstruktora. Posiadanie [wielu konstruktorów jest anty-wzorem] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97). – Steven

+0

Tak, to nie jest idealne. Wymyślę obejście. –

+0

Jeśli przeczytasz [artykuł] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=97) całkowicie, zobaczysz, że odpowiedź jest prosta. W przypadku kontrolowanego typu: usuń jednego konstruktora. Jeśli ten "MyTagHelper" jest stroną trzecią lub typem struktury, zarejestruj go za pomocą delegata fabrycznego i wywołaj określonego konstruktora wewnątrz tego delegata. – Steven

Odpowiedz

9

Illya ma rację: wbudowany rezolwerem nie obsługuje typy wystawiania wielu konstruktorów ... ale nic nie uniemożliwia rejestracji delegata na poparcie tego scenariusza:

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

Dzięki, przydaje się to do okablowania bibliotek innych firm, nad którymi nie sprawuję kontroli. – SimonGates

1

ASP.NET Core 1.0 Odpowiedź

Pozostałe odpowiedzi są nadal prawdziwe dla parametrów konstruktory pozbawione języka, np. jeśli masz klasę z konstruktorem bez parametrów i konstruktorem z argumentami, wyjątek w pytaniu zostanie zgłoszony.

Jeśli masz dwa konstruktory z argumentami, zachowanie polega na użyciu pierwszego zgodnego konstruktora, w którym są znane parametry. Możesz zapoznać się z kodem źródłowym klasy ConstructorMatcher w celu uzyskania szczegółów: here.

0

ASP.NET Rdzeń Odpowiedź

ja skończyło się z poniższym obejście dopóki nie naprawić/poprawić ten wynik.

Najpierw, zadeklaruj tylko jednego contruktora w kontrolerze (przekazując tylko wymagane ustawienia konfiguracyjne), biorąc pod uwagę, że obiekty ustawień przekazywane w konstruktorze mogą mieć wartość null (.NET Core będzie je automatycznie wstrzykiwać, jeśli skonfigurujesz je w metodzie uruchamiania):

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); 
     } 
    } 
} 

Następnie w swoich metodach testy można instancji kontrolera na dwa sposoby:

  1. drwi z nazwami opcji sprzeciw podczas konstruowania badanego obiektu
  2. Skonfiguruj przekazywanie wartości null we wszystkich parametrach, a następnie Zastąp zależności, które będą używane w testach.Masz następujący przykład:
[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; 
     } 
    } 

Od tego momentu można mieć pełne badanie z wtryskiem zależność i szydząc gotowy w .NET Core.

Mam nadzieję, że pomaga