【问题标题】:Ninject: GetAll instances that inherit from the same abstract classNinject:GetAll 继承自同一个抽象类的实例
【发布时间】:2015-07-16 21:48:07
【问题描述】:

Ninject 是否可以获取从特定抽象类继承的所有实例?例如,我有以下抽象类。

public abstract class MyAbstractClass { }

然后我有以下两个派生类,它们都继承自同一个抽象类。

public class MyDerivedClass1 : MyAbstractClass { }

public class MyDerivedClass2 : MyAbstractClass { }

现在我要将两个派生类与内核绑定,因为我希望它们处于单例范围内。

_kernel = new StandardKernel();
_kernel.Bind<MyDerivedClass1>().ToSelf().InSingletonScope();
_kernel.Bind<MyDerivedClass2>().ToSelf().InSingletonScope();

我知道内核可以向我返回如下实例。

_kernel.Get<MyDerivedClass1>();

有没有办法获取所有继承自 MyAbstractClass 的类?我尝试了以下但没有成功。

IEnumerable<MyAbstractClass> items = kernel.GetAll<MyAbstractClass>();

希望上面的 GetAll() 方法会返回一个包含两个实例的列表,一个是 MyDerivedClass1,第二个是 MyDerivedClass2。

【问题讨论】:

    标签: c# inheritance dependency-injection ninject abstract-class


    【解决方案1】:

    目前,您仅使用ToSelf 绑定到实现类型,而不是基类类型。它实际上是在调用_kernel.Bind&lt;MyDerivedClass1&gt;().To&lt;MyDerivedClass1&gt;()

    要将实现类型绑定到基类型,请使用:

    _kernel = new StandardKernel();
    _kernel.Bind<MyAbstractClass>().To<MyDerivedClass1>().InSingletonScope();
    _kernel.Bind<MyAbstractClass>().To<MyDerivedClass2>().InSingletonScope();
    
    //returns both
    var allImplementations = _kernel.GetAll<MyAbstractClass>();
    

    编辑:多个绑定到单例。

    _kernel = new StandardKernel();
    _kernel.Bind<MyDerivedClass1>().ToSelf().InSingletonScope();
    _kernel.Bind<MyDerivedClass2>().ToSelf().InSingletonScope();
    
    _kernel.Bind<MyAbstractClass>().ToMethod(x => _kernel.Get<MyDerivedClass1>());
    _kernel.Bind<MyAbstractClass>().ToMethod(x => _kernel.Get<MyDerivedClass2>());
    

    【讨论】:

    • 太棒了!这正是我所需要的。谢谢。
    • 我不确定 InSingletonScope 是否按预期工作。当我调用 _kernel.GetAll() 时,我可以看到按预期为 MyDerivedClass1 和 MyDerivedClass2 调用构造函数,但是当我调用 _kernel.Get() 时,我看到它的构造函数被再次调用。我希望这个 Get() 调用只会返回从 GetAll 调用创建的 MyDerivedClass1 的当前实例。
    • _kernel.Get&lt;MyDerivedClass1&gt;() 正在寻找绑定到MyDerivedClass 的实例/类型。 Ninject 对多个绑定使用同一个实例有点烦人。请参阅我的编辑。
    【解决方案2】:

    除了创建两个绑定,第二个绑定“重定向”到第一个,您还可以做的是:

    _kernel.Bind<MyAbstractClass, MyDerivedClass1>()
           .To<MyDerivedClass1>().InSingletonScope();
    _kernel.Bind<MyAbstractClass, MyDerivedClass2>()
           .To<MyDerivedClass1>().InSingletonScope();
    

    这更清楚地表达了意图。

    【讨论】:

    • 谢谢你用更少的代码做到了这一点!是否可以为所有从 MyAbstractClass 自动继承的类创建这种单例绑定?也许 Ninect 和 Reflection 的某种组合可以找到所有继承自 MyAbstractClass 的具体类?
    • @eric 是的。您可以为此查看Ninject.Extensions.Conventions。如果您需要更多信息,可能已经有关于 SO 的问题或类似情况。如果没有,您当然可以发布一个新问题。
    【解决方案3】:

    因此,如果您需要从抽象类继承单例并通过 GetAll 或 Get 使用它,它的工作方式如下:

    public abstract class Test
    {
        public string Name;
        public Test(string s)
        {
            Name = s;
        }
    }
    
    public class T1 : Test
    {
        public T1() : base("T1")
        {
        }
    }
    
    public class T2 : Test
    {
        public T2() : base("T2")
        {
        }
    }
    

    然后:

        static StandardKernel kernel;
        static void Main(string[] args)
        {
            kernel = new StandardKernel(new LoadModule());    
    
            var tests = kernel.GetAll<Test>();
            tests.ToList().ForEach(c => Console.WriteLine(c.Name));
            Console.WriteLine();
    
            Console.WriteLine(GetByType<T1>().Name);
            var z = GetByType<T1>();
            z.Name = "abc";           
            Console.WriteLine(z.Name);
            Console.WriteLine(GetByType<T1>().Name);
    
            Console.WriteLine();
    
            Console.WriteLine(GetByType<T2>().Name);
            var za = GetByType<T2>();
            za.Name = "abc";
            Console.WriteLine(za.Name);
            Console.WriteLine(GetByType<T2>().Name);
    
            Console.WriteLine();
    
            tests = kernel.GetAll<Test>();
            tests.ToList().ForEach(c => Console.WriteLine(c.Name));
            Console.WriteLine();
    
            Console.ReadKey();
    
    
    
        }
    
        static public T GetByType<T>()
        {
            return kernel.Get<T>();
        }
    
        public class LoadModule : NinjectModule
        {
            public override void Load()
            {    
                this.Bind<Test, T1>().To<T1>().InSingletonScope();
                this.Bind<Test>().To<T2>();
    
            }
        }
    

    按预期输出:

        T1
        T2
    
    
        T1
        abc
        abc
    
        T2
        abc
        T2
    
        abc
        T2
    

    【讨论】:

      猜你喜欢
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 2018-06-28
      • 1970-01-01
      • 1970-01-01
      • 2011-11-03
      • 2022-01-11
      相关资源
      最近更新 更多