私はこれに従っています チュートリアル 私はDbContext
を追加のコンストラクタを持つように修正するまでとてもうまくいきました。私は今解決に問題を抱えており、これを修正するために何をすべきかわからない。パラメータのないコンストラクタを取得するように強制する簡単な方法はありますか、それとも私はこれに近づいていますか?
2つのコンストラクタを持つ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
code:
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)
チュートリアルは素晴らしく、私が2番目のコンストラクタを追加するまではうまく機能していました。
何が起こっているのか、あなたはこの問題に噛まれているのです。基本的には、コンテナーにコントローラーを明示的に登録していないということです。 Unityは未登録の具象タイプを解決しようとしますが、解決できないため(設定のエラーが原因で)、nullを返します。 IDependencyResolver
コントラクトが原因でWeb APIが強制的にNULLを返すようにするため、強制的にnullが返されます。 Unityはnullを返すので、Web APIはコントローラ自体を作成しようとしますが、デフォルトのコンストラクタがないため、「コントローラにパラメータのないパブリックコンストラクタがあることを確認する」という例外がスローされます。この例外メッセージは誤解を招く可能性があり、実際の原因を説明するものではありません。
コントローラを明示的に登録した場合は、はるかに明確な例外メッセージが表示されたはずです。そのため、すべてのルートタイプを常に明示的に登録する必要があります。
しかしもちろん、設定エラーはあなたがあなたのDbContext
に2番目のコンストラクタを追加することから来ます。 Unityは常に引数が最も多いコンストラクタを選択しようとしますが、この特定のコンストラクタをどのように解決するかはわかりません。
だから本当の原因はあなたがDbContext
を作成するためにUnityの自動配線機能を使用しようとしていることです。 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>();
プロジェクトをコンパイルすると、コンパイラは文句を言って上の行で停止し、エラーを表示しました。
私は同じ問題を抱えていました。私はそれを2日間グーグルしました。ついに私は誤って問題がコントローラのコンストラクタのアクセス修飾子であることに気づきました。私はpublic
というキーワードをControllerのコンストラクタの後ろに置きませんでした。
public class MyController : ApiController
{
private readonly IMyClass _myClass;
public MyController(IMyClass myClass)
{
_myClass = myClass;
}
}
私はこの経験を別の答えとして付け加えていますが、他の誰かが同じような間違いをしたのかもしれません。
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;
}
コントローラにインターフェースがある場合
public myController(IXInterface Xinstance){}
それらをDependency Injectionコンテナに登録する必要があります。
container.Bind<IXInterface>().To<XClass>().InRequestScope();
あなたがnityConfig.csを使ってあなたのタイプのマッピングを以下のように登録するならば。
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IProductRepository, ProductRepository>();
}
あなたはContainerについて**webApiConfig.cs**
を知らせなければなりません
config.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(UnityConfig.Container);