如何使用Ninject在子类中创建实例?

时间:2012-04-10 15:30:57

标签: dependency-injection inversion-of-control ninject

我正在学习如何将nInject用于我正在开发的新应用程序,并且我创建了以下示例代码,可以将其复制/粘贴到一个简单的控制台应用程序中。它成功返回了一个IFoo实例,但我有一个问题。

如何修改代码以使FooManager类创建Foo对象的实例而不执行“new”。核仁也必须注射吗?但是如果注入了内核并且我将该行更改为读取var foo = _kernel.Get<IFoo>(),那么引入服务定位器反模式是不是?

namespace IOCTest
{
    class Program
    {
        static void Main(string[] args)
        {
            using (IKernel kernel = new StandardKernel(new StandardModule()))
            {
                // do something with the kernal
                var mgr = kernel.Get<IFooManager>();
                var foo = mgr.GetById(1);
            }
        }
    }

    public class StandardModule : Ninject.Modules.NinjectModule
    {
        public override void Load()
        {
            Bind<IDatabase>()
                .To<Database>()
                .InTransientScope();

            Bind<IFooManager>()
                .To<FooManager>()
                .InTransientScope();
        }
    }

    //******************************************************

    public interface IDatabase
    {
        object[] GetScalar(int id);
    }

    public class Database : IDatabase
    {
        public object[] GetScalar(int id)
        {
            return new object[] { "RowName" };
        }
    }

    //******************************************************

    public interface IFooManager
    {
        IFoo GetById(int id);
    }

    public class FooManager : IFooManager
    {
        private IDatabase _db;

        public FooManager(IDatabase db) { _db = db; }

        public IFoo GetById(int id)
        {
            var results = _db.GetScalar(id);
            var foo = new Foo();   // <-- HOW DO I ELIMINATE THIS DEPENDENCY?
            foo.Name = results[0].ToString();
            return foo;
        }
    }

    //******************************************************

    public interface IFoo
    {
        string Name { get; set; }
    }

    public class Foo : IFoo
    {
        public string Name { get; set; }
    }

    //******************************************************
}

2 个答案:

答案 0 :(得分:4)

首先你必须考虑Foo的目的。这是某种datacontainer还是某种服务?

在第一种情况下,您的代码就像它一样完美。 Datacontainers没有依赖关系,不应由IoC容器创建。

在第二个案例中阅读了关于Ninject.Extensions.Factory。

http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/

https://github.com/ninject/ninject.extensions.factory/wiki

答案 1 :(得分:2)

有几种方法可以消除这种依赖性。您可以使用Database依赖项执行相同的操作并使用构造函数注入。你可以做房产注射(https://github.com/ninject/ninject/wiki/Injection-Patterns)。另一种方式,也许你正在寻找的是服务地点。为此,您可以更新您的FooManager ctor以要求IKernel。这将自动解决,然后您可以使用传入的内核来获取Foo。

public class FooManager : IFooManager
{
    private IDatabase _db;
    private IKernel _kernel;

    public FooManager(IDatabase db, IKernel kernel) { _db = db; _kernel = kernel;}

    public IFoo GetById(int id)
    {
        var results = _db.GetScalar(id);
        // var foo = new Foo();   // <-- HOW DO I ELIMINATE THIS DEPENDENCY?
        var foo = kernel.Get<IFoo>(); // Like this perhaps
        foo.Name = results[0].ToString();
        return foo;
    }
}