Ninject - 如何以及何时注射 [英] Ninject - how and when to inject

查看:150
本文介绍了Ninject - 如何以及何时注射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个新手,当涉及到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(s​​tring 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 但我无处可去。



我确定这是一个微不足道的问题,但我似乎找不到
如何

解决方案

您直接新建 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 news 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆