C# · 12月 23, 2021

c# – 使用基于Ninject约定的绑定的正确方法是什么?

我主要使用Ninject作为手动绑定,如波纹管.哪个工作正常 kernel.Bind<TestContext>().ToSelf().InRequestScope();kernel.Bind<ITestRepository>().To<TestRepository>();

但是当我尝试使用基于约束的绑定绑定时,有点困惑,什么时候使用?

我经历了这个Ninject Documentation但是我找不到很多例子.

根据我的所有Repository类实现IRepository<型号>.因此,如果我想以传统方式进行绑定,那么下面的代码可以正常工作.

kernel.Bind(x => x .FromAssembliesMatching(“*”) .SelectAllClasses() .InheritedFrom(typeof(IRepository<>)) .BindDefaultInterface());

但我有点困惑

1.当我更改.FromAssembliesMatching(“*”)到.FromThisAssembly()时它无法正常工作,并抛出错误激活ITestRepository为什么?

2.并且当更改时.SelectAllClasses()To .SelectAllIncludingAbstractClasses()与.FromAssembliesMatching(“*”)的组合它是否正常工作,为什么?

让我解释一下我的代码结构.

IRepository(在DLL 1中)

public interface IRepository<E>{ E Get();}

RepositoryBase(在DLL 1中)

public abstract class RepositoryBase<E> : IRepository<E> where E : class{ public E Get() { return System.Activator.CreateInstance<E>(); // this is just for testing }}

TestRepository(在DLL 2中)

public interface ITestRepository : IRepository<TestModel>{}public class TestRepository : RepositoryBase<TestModel>,ITestRepository{}

现在使用Controller(在DLL 3中)

private readonly ITestRepository _testRepository; public HomeController(ITestRepository testRepository) { _testRepository = testRepository; }

请告诉我通过传统绑定最好的方法是什么?

注意DLL 1,2,3表示不同的项目

额外

错误详情

Server Error in ‘/’ Application.Error activating ITestRepositoryNo matching bindings are available,and the type is not self-bindable.Activation path: 2) Injection of dependency ITestRepository into parameter testRepository of constructor of type HomeController 1) Request for HomeControllerSuggestions: 1) Ensure that you have defined a binding for ITestRepository. 2) If the binding was defined in a module,ensure that the module has been loaded into the kernel. 3) Ensure you have not accidentally created more than one kernel. 4) If you are using constructor arguments,ensure that the parameter name matches the constructors parameter name. 5) If you are using automatic module loading,ensure the search path and filters are correct.Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: Ninject.ActivationException: Error activating ITestRepositoryNo matching bindings are available,ensure the search path and filters are correct.Source Error: An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.Stack Trace: [ActivationException: Error activating ITestRepositoryNo matching bindings are available,and the type is not self-bindable.Activation path: 2) Injection of dependency ITestRepository into parameter testRepository of constructor of type HomeController 1) Request for HomeControllerSuggestions: 1) Ensure that you have defined a binding for ITestRepository. 2) If the binding was defined in a module,ensure that the module has been loaded into the kernel. 3) Ensure you have not accidentally created more than one kernel. 4) If you are using constructor arguments,ensure that the parameter name matches the constructors parameter name. 5) If you are using automatic module loading,ensure the search path and filters are correct.] Ninject.KernelBase.Resolve(IRequest request) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:359 Ninject.Planning.Targets.Target`1.GetValue(Type service,IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:197 Ninject.Planning.Targets.Target`1.ResolveWithin(IContext parent) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Targets\Target.cs:165 Ninject.Activation.Providers.StandardProvider.GetValue(IContext context,ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:114 Ninject.Activation.Providers.<>c__DisplayClass4.<Create>b__2(ITarget target) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:96 System.Linq.WhereSelectArrayIterator`2.MoveNext() +66 System.Linq.Buffer`1..ctor(IEnumerable`1 source) +216 System.Linq.Enumerable.ToArray(IEnumerable`1 source) +77 Ninject.Activation.Providers.StandardProvider.Create(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Providers\StandardProvider.cs:96 Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:157 Ninject.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.cs:386 System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +145 System.Linq.Enumerable.SingleOrDefault(IEnumerable`1 source) +4098209 Ninject.Web.Mvc.NinjectDependencyResolver.GetService(Type serviceType) in c:\Projects\Ninject\ninject.web.mvc\mvc3\src\Ninject.Web.Mvc\NinjectDependencyResolver.cs:56 System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext,Type controllerType) +41[InvalidOperationException: An error occurred when trying to create a controller of type ‘MVCPluginApproach.Controllers.HomeController’. Make sure that the controller has a parameterless public constructor.] System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext,Type controllerType) +179 System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext,Type controllerType) +80 System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext,String controllerName) +74 System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext,IController& controller,IControllerFactory& factory) +197 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext,AsyncCallback callback,Object state) +49 System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext,Object state) +50 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context,AsyncCallback cb,Object exTradata) +16 System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301 System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean& completedSynchronously) +155

**根据我的基本理解……导致错误的多个装配,单个装配的设置.因此,当我尝试通过.FromThisAssembly()绑定它时,Ninject无法解析它.这是真的吗?

解决方法 这是我如何用Ninject 3.0做的… //binding rules in all assemblies named “My.<anything>.dll”kernel.Bind(x => x.FromAssembliesMatching(“My.*.dll”) .SelectAllClasses() .BindAllInterfaces() );// basic interfaceISomething<T> { /* code for interface */ }// implementation of interfaceSomething<T> { /* implement interface */ }// get an instance of Something<AnyType> by asking for ISomething<AnyType>var something = kernel.Get<ISomething<SomeType>>();

然后,您需要做的就是声明更多的接口和类.

当你想使用抽象类/继承时,最简单的方法就是做这样的事情…

ICustomSomething : ISomething<SomeType> { /* extended interface parts */ }CustomSomething : Something<SomeType>,ICustomSomething { /* implement ICustomSomething */ }

不需要新的依赖规则.
这里使用的约定基本上意味着Ninjects核心将寻找I …然后通过查找具有相同名称的类型减去I前缀作为一般经验法则来匹配类型,因此对于您定义的每个新类/类型只需为它声明一个接口,ninject不需要更多信息.

如果你想做更复杂的事情(比如说多态场景)那么我建议让ninject创建一个你给你的类型的工厂,然后从中吐出正确的类型.

所以你可以……

kernel.Bind<ISomething<>>().ToMethod(() => () { kernel.Get<SomeFactory>().Get<T>() });

对不起,如果这里的代码并不完全是在我头上的ram,但你应该能够从中得到这个想法:)

编辑:
观察……
值得注意的是,这往往不起作用:

kernel.Bind(x => x.FromAssembliesMatching(“*”) …);

指令“.FromAssembliesMatching(”*“)”将逐字地拾取bin文件夹中的所有程序集并尝试为它们构建规则,我经常发现某些第三方创建的程序集不能以这种方式处理,您也可能您的bin文件夹中的.Net块,您不希望为其构建规则.

我打了一些砖墙,并决定创建我自己的程序集命名约定所以我有像…

MyCorp.Core.dll;
MyCorp.Common.dll;
MyCorp.AppName.Repositories.dll;
MyCorp.AppName.Services.dll;

所以当我绑定时,我只绑定这些程序集而不是使用所有内容

.FromAssembliesMatching(“MyCorp.*.dll”)

除此之外我发现Ninject的问题很少,这是非常基本的东西!