Ninject - 如何以及何时注射 [英] Ninject - how and when to inject
问题描述
我是一个新手,当涉及到DI和ninject,我正在努力一点
关于实际注射应该发生和如何启动
绑定。
我已经在我的网络应用程序中使用它,它的工作正常,
,但现在我想在类库中使用注入。
说我有一个这样的类:
public class TestClass
{
[Inject]
public IRoleRepository RoleRepository {get;组; }
[Inject]
public ISiteRepository SiteRepository {get;组; }
[Inject]
public IUserRepository UserRepository {get;组; }
private readonly string _fileName;
public TestClass(string fileName)
{
_fileName = fileName;
}
public void ImportData()
{
var user = UserRepository.GetByUserName(myname);
var role = RoleRepository.GetByRoleName(myname);
var site = SiteRepository.GetByID(15);
//使用文件等
}
}
我想在这里使用属性注入,因为我需要在我的构造函数中传入一个
文件名。我正确地说,如果我需要
传递一个构造函数参数,我不能使用构造函数注入?
如果我可以使用构造函数注入附加参数,那么
如何传递这些参数?
我有一个控制台应用程序消耗的测试看起来像
的类如下:
class Program
{
static void Main(string [] args)
{
// NinjectRepositoryModule将我的IRoleRepository等绑定到具体的
//类型,可以正常工作,因为我在我的Web应用程序中使用它任何
//问题
IKernel kernel = new StandardKernel(new NinjectRepositoryModule());
var test = new TestClass(filename);
test.ImportData();
}
}
我的问题是当我打电话 test.ImportData()
我的存储库为空 - 没有注入到它们中。我尝试创建另一个模块,并调用
绑定< TestClass>()。ToSelf();
,因为我以为这可能会解决 TestClass $ c中的所有注入属性$ c>但我无处可去。
我确定这是一个微不足道的问题,但我似乎找不到
如何
您直接新建 TestClass
,其中Ninject没有办法拦截 - 记住没有像代码转换拦截你的新的
等等的魔术。
你应该要做 kernel.Get< TestClass>
。
如果没有,你可以在你之后注入 c code code code $ kernel.Inject(test);
我认为wiki中有一篇关于 Inject
vs Get
等的文章。请注意,一般来说,直接获取
或注入
调用是一个做错了服务位置的气味,这是一个反刍动物燕鸥。在您的网络应用程序的情况下, NinjectHttpModule
和 PageBase
是拦截对象创建的钩子 - 有类似的拦截器/其他样式的应用程序拦截的逻辑位置。
重新使用绑定&TestClass>()。ToSelf()
,通常一个 StandardKernel
有 ImplicitSelfBinding = true
这将使得不必要(除非你想影响其范围是除了 .InTransientScope()
之外的其他东西。
最后的风格点: - 您正在使用属性注入。这很少有很好的理由,所以你应该使用构造函数注入。
并且去买 @Mark Seemann的.NET中的依赖注入,这里有一堆优秀的帖子,涵盖了依赖注入区域及其周围的许多重要而微妙的考虑。
I'm a newbie when it comes to DI and ninject and I'm struggling a bit about when the actual injection should happen and how to start the binding.
I'm using it already in my web application and it working fine there, but now I want to use injection in a class library.
Say I have a class like this:
public class TestClass
{
[Inject]
public IRoleRepository RoleRepository { get; set; }
[Inject]
public ISiteRepository SiteRepository { get; set; }
[Inject]
public IUserRepository UserRepository { get; set; }
private readonly string _fileName;
public TestClass(string fileName)
{
_fileName = fileName;
}
public void ImportData()
{
var user = UserRepository.GetByUserName("myname");
var role = RoleRepository.GetByRoleName("myname");
var site = SiteRepository.GetByID(15);
// Use file etc
}
}
I want to use property injection here because I need to pass in a filename in my constructor. Am I correct in saying that if I need to pass in a constructor parameter, I cannot use constructor injection? If I can use constructor injection with additional parameters, how do I pass those parameters in?
I have a console app that consumes by Test class that looks as follows:
class Program
{
static void Main(string[] args)
{
// NinjectRepositoryModule Binds my IRoleRepository etc to concrete
// types and works fine as I'm using it in my web app without any
// problems
IKernel kernel = new StandardKernel(new NinjectRepositoryModule());
var test = new TestClass("filename");
test.ImportData();
}
}
My problem is that when I call test.ImportData()
my repositories are null - nothing has been injected into them. I have tried creating another module and calling
Bind<TestClass>().ToSelf();
as I thought this might resolve all injection properties in TestClass
but I'm getting nowhere.
I'm sure this is a trivial problem, but I just can't seem to find out how to go about this.
You are directly newing TestClass
, which Ninject has no way of intercepting - remember there's no magic like code transformation intercepting your new
s etc.
You should be doing kernel.Get<TestClass>
instead.
Failing that, you can inject it after you new
it with a kernel.Inject( test);
I think there's an article in the wiki that talks about Inject
vs Get
etc.
Note that in general, direct Get
or Inject
calls are a Doing It Wrong smell of Service Location, which is an antipattern. In the case of your web app, the NinjectHttpModule
and PageBase
are the hook that intercepts object creation - there are similar interceptors / logical places to intercept in other styles of app.
Re your Bind<TestClass>().ToSelf()
, generally a StandardKernel
has ImplicitSelfBinding = true
which would make that unnecessary (unless you want to influence its Scope to be something other than .InTransientScope()
).
A final style point:- you're using property injection. There are rarely good reasons for this, so you should be using constructor injection instead.
And do go buy Dependency Injection in .NET by @Mark Seemann, who has stacks of excellent posts around here which cover lots of important but subtle considerations in and around the Dependency Injection area.
这篇关于Ninject - 如何以及何时注射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!