나는 추가 생성자를 갖도록 수정 하기 전까지 훌륭하게 작동 한이 튜토리얼 을 따랐다 DbContext
. 이제 해결에 문제가 있으며이 문제를 해결하기 위해 무엇을해야할지 모르겠습니다. 매개 변수가없는 생성자를 잡도록 강제하는 쉬운 방법이 있습니까? 아니면 잘못 접근하고 있습니까?
DbContext
두 개의 생성자 :
public class DashboardDbContext : DbContext
{
public DashboardDbContext() : base("DefaultConnection") { }
public DashboardDbContext(DbConnection dbConnection, bool owns)
: base(dbConnection, owns) { }
}
SiteController
건설자:
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
저장소:
DashboardDbContext _context;
public DashboardRepository(DashboardDbContext context)
{
_context = context;
}
UnityResolver
암호:
public class UnityResolver : IDependencyResolver
{
private readonly IUnityContainer _container;
public UnityResolver(IUnityContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
try
{
return _container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return _container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = _container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
_container.Dispose();
}
}
WebApiConfig :
var container = new UnityContainer();
container.RegisterType<IDashboardRepository, DashboardRepository>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
WebApi 호출 오류 :
System.InvalidOperationException : ‘SiteController’유형의 컨트롤러를 만들려고 할 때 오류가 발생했습니다. 컨트롤러에 매개 변수없는 공용 생성자가 있는지 확인하십시오.
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
at System.Web.Http.Controllers.HttpControllerDescriptor.CreateController(HttpRequestMessage request)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__0.MoveNext()
InnerException : System.ArgumentException : ‘Dashboard.Web.Controllers.SiteController’형식에 기본 생성자가 없습니다.
at System.Linq.Expressions.Expression.New(Type type)
at System.Web.Http.Internal.TypeActivator.Create[TBase](Type instanceType)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.GetInstanceOrActivator(HttpRequestMessage request, Type controllerType, Func`1& activator)
at System.Web.Http.Dispatcher.DefaultHttpControllerActivator.Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
튜토리얼은 훌륭했고 두 번째 생성자를 추가 할 때까지 잘 작동했습니다.
답변
무슨 일이 일어나고 있는지는 당신 이이 문제에 물렸다는 것입니다 . 기본적으로 컨테이너에 컨트롤러를 명시 적으로 등록하지 않은 것입니다. Unity는 등록되지 않은 구체적인 유형을 해결하려고 시도하지만 해결할 수 없기 때문에 (구성 오류로 인해) null을 반환합니다. Web API가 IDependencyResolver
계약 으로 인해 그렇게하도록 강제하기 때문에 null을 반환해야합니다 . Unity가 null을 반환하기 때문에 Web API는 컨트롤러 자체를 생성하려고 시도하지만 기본 생성자가 없기 때문에 “컨트롤러에 매개 변수없는 공개 생성자가 있는지 확인”예외가 발생합니다. 이 예외 메시지는 오해의 소지가 있으며 실제 원인을 설명하지 않습니다.
컨트롤러를 명시 적으로 등록했다면 훨씬 더 명확한 예외 메시지를 보았을 것이므로 항상 모든 루트 유형을 명시 적으로 등록해야합니다.
그러나 물론 구성 오류는 두 번째 생성자를 DbContext
. Unity는 항상 인수가 가장 많은 생성자를 선택하려고하지만이 특정 생성자를 해결하는 방법을 모릅니다.
따라서 실제 원인은 Unity의 자동 연결 기능을 사용하여 DbContext
. DbContext
자동 연결되어서는 안되는 특수 유형입니다. 프레임 워크 유형 이므로 팩토리 대리자를 사용하여 등록하는 것으로 대체 해야합니다 .
container.Register<DashboardDbContext>(
new InjectionFactory(c => new DashboardDbContext()));
답변
제 경우에는 삽입 된 종속성의 생성자 내부의 예외 때문이었습니다 (예 : DashboardRepository 생성자 내부). MVC 인프라 내부 어딘가에서 예외가 발견되었습니다. 관련 장소에 로그를 추가 한 후 이것을 발견했습니다.
답변
동일한 문제가 발생하여 UnityConfig.cs 파일을 변경하여 해결했습니다. UnityConfig.cs 파일에서 종속성 문제를 해결하려면 다음을 추가해야합니다.
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
답변
때로는 ContainerBootstraper.cs에서 인터페이스를 해결하기 때문에 오류를 포착하기가 매우 어렵습니다. 제 경우에는 API 컨트롤러에 삽입 한 인터페이스의 구현을 해결하는 데 오류가 발생했습니다. 내 bootstraperContainer에서 인터페이스를 container.RegisterType<IInterfaceApi, MyInterfaceImplementaionHelper>(new ContainerControlledLifetimeManager());
다음 과 같이 해결했기 때문에 오류를 찾을 수 없습니다.
그런 다음 부트 스트랩 컨테이너에 다음 줄을 추가했습니다. container.RegisterType<MyController>();
그래서 프로젝트를 컴파일 할 때 컴파일러가 불평하고 위 줄에서 중지하고 오류를 표시했습니다. .
답변
나는 같은 문제가 있었다. 나는 이틀 동안 그것을 봤다. 마침내 문제가 컨트롤러 생성자의 액세스 수정 자라는 것을 우연히 발견했습니다. public
Controller의 생성자 뒤에 핵심 단어를 넣지 않았습니다 .
public class MyController : ApiController
{
private readonly IMyClass _myClass;
public MyController(IMyClass myClass)
{
_myClass = myClass;
}
}
나는이 경험을 다른 대답으로 추가하면 다른 사람이 비슷한 실수를했을 수 있습니다.
답변
컨트롤러에 인터페이스가있는 경우
public myController(IXInterface Xinstance){}
종속성 주입 컨테이너에 등록해야합니다.
container.Bind<IXInterface>().To<XClass>().InRequestScope();
답변
UnityContainer에서 정의한 인터페이스 유형 대신 실수로 속성을 특정 객체 유형으로 정의하면이 오류가 발생합니다.
예를 들면 :
UnityContainer 정의 :
var container = new UnityContainer();
container.RegisterInstance(typeof(IDashboardRepository), DashboardRepository);
config.DependencyResolver = new UnityResolver(container);
SiteController (잘못된 방법-저장소 유형 알림) :
private readonly DashboardRepository _repo;
public SiteController(DashboardRepository repo)
{
_repo = repo;
}
SiteController (올바른 방법) :
private readonly IDashboardRepository _repo;
public SiteController(IDashboardRepository repo)
{
_repo = repo;
}
