假设我有一个服务接口:
public interface IFooService
{
void DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
并且该服务的具体实现是通用的:
public class FooService<TRequestingClass> : IFooService
{
public virtual void DoSomething() { }
}
Run Code Online (Sandbox Code Playgroud)
我还有一些需要IFooService实例的其他类:
public class Bar
{
private IFooService _fooService;
public Bar(IFooService fooService)
{
this._fooService = fooService;
}
}
Run Code Online (Sandbox Code Playgroud)
我需要连接我的IoC容器,这样当创建Bar时,它会传递一个FooService <Bar>的构造函数参数.还有很多其他课程就像Bar一样.每个人都可能需要传递给他们的FooService <TRequestingClass>实例,其中TRequestingClass是需要IFooService实例的类的类型.我不需要向IFooService的消费者公开这个怪癖.他们应该关心的是他们可以调用他们传递的IFooService的方法.他们不应该知道他们传递的IFooService的具体实现需要任何特殊的构造.
FooService <T>的可接受的替代方法是一个非泛型类,在其构造函数中包含一个字符串参数,该参数包含为其创建的类的名称.即:
public class FooService : IFooService
{
public FooService(string requestingClassName) { }
}
Run Code Online (Sandbox Code Playgroud)
如何通过这种方式连接我的IoC容器来构建依赖项?
如果你为什么我想要这样一个奇怪的结构而感到困惑,那么考虑当你得到一个用log4net.LogManager.GetLogger(typeof(SomeClass))创建的ILog时log4net如何工作得最好.我不想通过引用log4net来丢弃我的代码,所以我想编写一个简单的ILogger接口,并用这样的方式实现它:
public class GenericLogger<T> : ILogger
{
private readonly ILog log;
public GenericLogger()
{
this.log = log4net.LogManager.GetLogger(typeof(T));
}
public void Debug(object message)
{ …Run Code Online (Sandbox Code Playgroud) 我正在尝试将Ninject 2.0与Asp .Net 3.5 Web应用程序一起使用.以下是我正在使用的DLLS及其版本.
在我的global.ascx.cs中,我有以下方法.
protected override IKernel CreateKernel()
{
IKernel kernel = new StandardKernel();
kernel.Bind<IDataAccess>().To<DataAccessEntBlock>().InSingletonScope();
return kernel;
}
Run Code Online (Sandbox Code Playgroud)
当我运行应用程序时,我得到以下错误.
Error activating ILoggerFactory
No matching bindings are available, and the type is not self-bindable.
Activation path:
1) Request for ILoggerFactory
Suggestions:
1) Ensure that you have defined a binding for ILoggerFactory.
2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.
3) Ensure …Run Code Online (Sandbox Code Playgroud) 我见过的几乎所有Ninject示例都解释了如何在ASP.NET MVC中使用它,它会自动将依赖项注入控制器.我如何手动使用Ninject?假设我有一个自定义ActionResult:
public class JsonResult : ActionResult
{
[Inject] public ISerializer Serializer { get; set; }
public JsonResult(object objectToSerialize)
{
// do something here
}
// more code that uses Serializer
}
Run Code Online (Sandbox Code Playgroud)
然后在我的控制器中,我正在使用这样JsonResult的方法:
public ActionResult Get(int id)
{
var someObject = repo.GetObject(id);
return new JsonResult(someObject);
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,我自己实例化了这个对象,它回避了Ninject的注入,并且Serializer将为null.但是,按照以下方式执行此操作对我来说似乎并不合适:
public ActionResult Get(int id)
{
var someObject = repo.GetObject(id);
return IoC.Kernel.Get<JsonResult>(someObject);
}
Run Code Online (Sandbox Code Playgroud)
因为现在控制器中不仅存在对Ninject的依赖,而且还必须在静态类/单例中公开Ninject内核,并确保依赖注入的对象仅通过内核创建.
有没有办法以某种方式配置Ninject注入依赖,而不依赖于暴露内核?new如果可能的话,我希望能够使用关键字.
dependency-injection ninject inversion-of-control actionresult asp.net-mvc-2
我有一个GUI应用程序.在其中,我允许用户从容器提供的算法列表中进行选择.每个算法将在另一个视图中作为后台任务启动.我需要支持此视图的多个实例,并支持同一算法的多个实例.该视图也将由容器提供.该算法也是有状态的.
所以我有一个案例,我需要创建我的视图和算法的实例,并在运行时将它们绑定在一起.我没有这些实例的静态绑定点,所以我不能使用正常的注入工具(构造函数或属性注入).我不想打电话new,我不想像服务定位器那样使用容器.
我在Castle.Windsor中使用Typed Factory Facility解决了这个问题,但我不得不在我的应用程序中处理工厂.工厂设计也有点奇怪,因为当我完成它们时,我不得不将我的实例返回工厂.
我现在正在研究使用NInject,因为到目前为止,学习曲线和介绍文档要好得多,我想为我的团队提出一个容器供我使用.但是对于这样的场景,我认为我必须编写自己的工厂并直接调用内核来解析新实例(嵌入在工厂中的Service Locator),以及在我的注册码中添加工厂方法.
是否有一种通用的方法来解决这个问题,或者这只是一个依赖注入本身不能解决的问题?
澄清:
我在评论中说我想要一个Ninject的具体答案,我已经得到了.非常感谢:)在现实生活中,我可能只是使用已经提出的实用解决方案.
但是我把我的基础作为一个具体的问题来解决我的问题.我希望在标题中对这个问题有一个更纯粹的基本答案.
是否有纯DI技术允许用户在运行时触发组件的新实例?或者所有这些实现都将容器用作服务定位器,或者需要对容器的特定"怪癖"(例如内置工厂支持,ala Castle.Windsor或即将发布的Ninject工厂特性),而不是而只利用"纯"DI的方方面面?
我只听说过Java世界中的这个词,我对它的含义并不太了解 - 请原谅我:)我正在寻找某种"注射"吗?
如果我有10个依赖项,我需要注入,并且不希望在构造函数中有10个参数,我应该使用哪种注入模式?
public class SomeClass
{
private IDependency1 _dependency1;
private IDependency2 _dependency2;
private IDependency3 _dependency3;
//...
}
Run Code Online (Sandbox Code Playgroud)
我应该使用setter方法注入吗?
public class SomeClass
{
private IDependency1 _dependency1;
private IDependency2 _dependency2;
private IDependency3 _dependency3;
//...
[Inject]
public void SetDependency1(IDependency1 dependency1)
{
_dependency1 = dependency1;
}
//...
}
Run Code Online (Sandbox Code Playgroud)
还是物业注入?
public class SomeClass
{
[Inject]
public IDependency1 Dependency1 { private get; set; }
[Inject]
public IDependency2 Dependency2 { private get; set; }
[Inject]
public IDependency3 Dependency3 { private get; set; }
//...
}
Run Code Online (Sandbox Code Playgroud)
根据Ninject wiki,只写上面的属性被认为是不好的做法,但是它与上面的setter方法注入不一样,只是更少的代码?
对于这种情况,哪种模式最有意义?
我有一个使用MVC的沼泽标准三层项目的问题,我正在尝试使用Ninject.我有一个MemberRepository:
public class MemberRepository : IMemberRepository{
public bool Save(Member member){
//saves member
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有我的服务层:
public class MemberService : IMemberService{
public bool Register(string email){
//Do Stuff & Populate Member Object
_repo.Save(member);
}
}
Run Code Online (Sandbox Code Playgroud)
鉴于我将使用Ninject,我设置AccountController的最佳方式是什么.我应该将MemberService传递给构造函数,如下所示:
public class AccountController : Controller
{
IMemberService _memberService;
public AccountController(IMemberService memberService)
{
_memberService = memberService;
}
}
Run Code Online (Sandbox Code Playgroud)
或者传入存储库:
public class AccountController : Controller
{
IMemberService _memberService;
public AccountController(IMemberRepository memberRepo)
{
_memberService = new MemberService(memberRepo);
}
}
Run Code Online (Sandbox Code Playgroud)
或两者?
我最初只有一个存储库(没有服务层),但我必须实现一个服务层,我不知道如何在我的NinjectWebCommon.cs文件中注册内核时处理'依赖'.最初只是这个:
kernel.Bind<IMemberRepository>().To<SqlMemberRepository>();
Run Code Online (Sandbox Code Playgroud)
但现在我想知道我是否需要注册IMemberService并将repo作为某种参数.
:s感觉有点丢失.希望我有意义,有人可以帮忙.
如果我有以下内容:
public MyClass(IServiceOne serviceOne, IServiceTwo serviceTwo, IServiceThree serviceThree = null)
{
this.serviceOne = serviceOne;
this.serviceTwo = serviceTwo;
this.serviceThree = serviceThree ?? new ServiceThree("some-info");
}
Run Code Online (Sandbox Code Playgroud)
我如何告诉Ninject绑定前两个参数,而不是IServiceThree类型的参数?这甚至可能吗?
我希望serviceThree作为构造函数参数的原因是可测试性 - 我需要能够从我的测试中注入一个mock.
我目前正在考虑将Ninject纳入我的单元测试中.通过与早期问题相关的一些非常聪明的帖子(什么是Ninject以及何时使用它?,http://martinfowler.com/articles/injection.html); 我想我得到了一些核心概念,但是如果它的应用程序我正在努力.
大多数情况下,当IOC包含器出现时,它与将它们合并到单元测试中有关.但是,从实际的角度来看,在我的单元测试中使用像Ninject这样的框架是否有意义,如果我还没有将它合并到我的实际代码库中呢?
举例说明下面的例子(使用C#从James Bender的专业测试驱动开发中取消:使用TDD开发真实世界的应用程序)
[TestFixture]
public class PersonServiceTests
{
[Test]
public void ShouldBeAbleToCallPersonServiceAndGetPerson()
{
var expected = new Person {Id = 1, FirstName = “John”, LastName = “Doe”};
var kernel = new StandardKernel(new CoreModule());
var personService = kernel.Get < PersonService > ();
var actual = personService.GetPerson(expected.Id);
Assert.AreEqual(expected.Id, actual.Id);
Assert.AreEqual(expected.FirstName, actual.FirstName);
Assert.AreEqual(expected.LastName, actual.LastName);
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用Ninject编写我的测试改善我的生活(或任何继承我的代码的可怜的开发人员),而不是仅仅编写我的测试:
[TestFixture]
public class PersonServiceTests
{
[Test]
public void ShouldBeAbleToCallPersonServiceAndGetPerson()
{
var expected = new Person {Id = 1, FirstName = …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用依赖注入和动作过滤器属性为普通的MVC控制器(而不是WebAPI)根据这个答案/sf/answers/433591161/
我见过的文章说你必须使用kernel.BindFilter<>(),但这不适用于我的内核.
using Ninject;
using Ninject.Web.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
using uQuiz.Domain;
using uQuiz.Domain.Abstract;
using uQuiz.Domain.Concrete;
using uQuiz.Domain.Models;
namespace uQuiz.WebUI.Infrastructure
{
/// <summary>
/// Dependency Resolver for Ninject, called within NinjectWebCommon.cs in App_start folder
/// </summary>
public class NinjectDependencyResolver : NinjectScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernelParam)
: base (kernelParam)
{
this.kernel = kernelParam;
this.AddBindings();
}
public IDependencyScope BeginScope()
{
return new NinjectScope(kernel.BeginBlock());
}
private void AddBindings()
{
this.kernel.Bind(typeof(IQuizEntities)).To(typeof(QuizEntities)).InRequestScope(); …Run Code Online (Sandbox Code Playgroud) 这是手头的问题:
在调用我CustomerController的时候URL,我得到以下异常:
ExceptionMessage:
尝试创建"CustomerController"类型的控制器时发生错误.确保控制器具有无参数的公共构造函数.
我使用以下网址:
请注意:
/api/Customer/在我将逻辑重构为业务类并实现依赖注入之前,调用正在进行.
我的研究表明,我没有正确地注册我的界面和课程Ninject,但不确定我错过了哪一步.
研究链接:
这是我的问题导致此异常的原因是什么?我正在注册我的接口/类
Ninject,但它似乎没有正确识别映射.有什么想法吗?
客户控制员
public class CustomerController : ApiController
{
private readonly ICustomerBusiness _customerBusiness;
public CustomerController(ICustomerBusiness customerBusiness)
{
_customerBusiness = customerBusiness;
}
// GET api/Customer
[HttpGet]
public IEnumerable<Customer> GetCustomers()
{
return _customerBusiness.GetCustomers();
}
// GET api/Customer/Id
[HttpGet]
public IEnumerable<Customer> GetCustomersById(int customerId)
{
return _customerBusiness.GetCustomerById(customerId);
}
}
Run Code Online (Sandbox Code Playgroud)
客户业务
public class CustomerBusiness : ICustomerBusiness
{
private readonly DatabaseContext …Run Code Online (Sandbox Code Playgroud)