【问题标题】:NInject: Create instances per user/session on convention bindingNInject:在约定绑定上为每个用户/会话创建实例
【发布时间】:2015-07-21 08:50:21
【问题描述】:

总结:

  1. 我在插件文件夹中的几个程序集上未定义未知的 IProducerPlugin 实现。
  2. 我有一个 Core 对象存储当前注册用户的列表。
  3. 核心是组合根。

所以,我需要:

  1. 创建与注册用户数量一样多的 IProducerPlugin 继承类对象。
  2. 当新用户取消/注册时,我需要创建/释放这些对象。

为了注册我的“插件”:

this.Kernel.Bind(b => b.FromAssembliesMatching("*")
            .SelectAllClasses()
            .InheritedFrom(typeof(Extensibility.IProducerPlugin))
            .BindAllInterfaces());

我不太清楚如何实现它。

你能帮帮我吗?

非常感谢您的帮助。

【问题讨论】:

    标签: ninject ninject-extensions


    【解决方案1】:

    一般的 DI 容器和特殊的 Ninject 适合在运行时添加和删除容器的新绑定。有些,如 Autofac,甚至不允许在创建容器后添加绑定。 Ninject 允许在任何时候添加新的绑定,但你不能永远删除它们(*在某些用例中有Rebind,但不一样)。

    kernel.Release(object) 没有删除绑定,它只是删除了对它所拥有的object 的所有引用。 例如:

    var foo = new object();
    kernel.Bind<object>().ToConstant(foo);
    

    要允许对foo 进行垃圾收集,您可以执行以下操作之一:

    • kernel.Release(foo);
    • kernel.Dispose(); kernel = null;

    这正是kernel.Release(...) 的用途。也许你也可以Release 一个单例,从而强制ninject 在下一个请求时创建一个新的。但我不知道这是否真的有效,如果有效,那肯定是一个出乎意料的黑客攻击。


    所以你应该做的是自己管理列表/字典。您可以使用 ninject 绑定和注入列表/字典/管理器无论您如何称呼它,但您不能让 ninject 管理器管理列表本身。

    【讨论】:

    • 谢谢。问题的重点在于如何创建所需的绑定。我已经使用具体类 (see this answer) 实现了这一点。但是我还没有想出如何在接口绑定上做这样的事情...请参阅我的下一个答案。
    • @Jordi 基本上是提供者封装了字典——如果你永远不需要删除一个条目,它就可以工作。否则它会变得更棘手。
    • 感谢@BatteryBackupUnit。但是,问题是我在我的提供程序上执行了GetAll&lt;IProduferPlugin&gt;Get&lt;IProducerPlugin&gt;,NInject 请求,好的,没问题。但是,在上下文参数中嵌入的Create 方法上收到的信息不包含有关先前注册的具体类的任何信息。这是主要问题(我已经注册了我的IProducerPlugin 接口的几个具体实现,但是,由于这些信息在任何地方,我还不太清楚如何在提供者上创建它们的实例。
    • @Jordi An IProvider 与绑定单个项目的GetAll 无关。您可以为整个集合(返回集合的提供程序)设置一个 IProvider,但是,使用 ninject 绑定集合 items 是没有意义的。
    【解决方案2】:

    我已经设法使用这个 IBindingGenerator 接口方法做类似的事情......

    我用过.BindWith&lt;&gt;()绑定方法...

    this.Kernel.Bind(b => b.FromAssembliesMatching("*")
                .SelectAllClasses()
                .InheritedFrom(typeof(Extensibility.IProducerPlugin))
                .BindWith<PluginBindingGenerator<Extensibility.IProducerPlugin>>()
            );
    

    我已经实现了一个 IBindingGenerator:

    public class PluginBindingGenerator<T> : IBindingGenerator
    {
        public System.Collections.Generic.IEnumerable<Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, Ninject.Syntax.IBindingRoot bindingRoot)
        {
            if (type != null && !type.IsAbstract && type.IsClass && typeof(T).IsAssignableFrom(type))
            {
                Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object> syntax = bindingRoot.Bind(typeof(Extensibility.IProducerPlugin)).ToProvider(new PluginProvider());
                yield return (Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax<object>)syntax;
            }
        }
    }
    
    public class PluginProvider : IProvider<object>
    {
    
        private System.Collections.Generic.Dictionary<Domain.Identity.ClientIdentity, Extensibility.IProducerPlugin> plugins;
    

    然后,提供者:

        public PluginProvider()
        {
            this.plugins = new System.Collections.Generic.Dictionary<Domain.Identity.ClientIdentity, Extensibility.IProducerPlugin>();
        }
    
        public object Create(IContext ctx)
        {
    
            //... I don't know what to do here...
    
            return objects;
        }
    
        public Type Type
        {
            get { throw new NotImplementedException(); }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-02
      • 1970-01-01
      • 1970-01-01
      • 2014-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      相关资源
      最近更新 更多