簡體   English   中英

是否可以設置Ninject綁定來創建同一類的多個實例?

[英]Is it possible to setup Ninject bindings to create multiple instances of same class?

我們有一個(奇怪的?)要求來創建X個相同類的實例,並且我們將Ninject用於IoC。 顯然,我們可以通過多次請求相同類型的對象來手動完成此操作:

for (var i = 0; i <= 10; i++)
{
    var obj = _kernel.GetService(typeof(MyType));
    ...
}

這可以按預期工作,但是現在我們必須訪問代碼中的內核才能做到這一點,而且“很臭”。 我更喜歡在綁定中處理它,就像InRequestScope一樣。

為了給所有這些增加一點復雜性,我們還指定了它自己的對象上的實例數,因此上面的代碼實際上更接近於此:var obj =(MyType)_kernel.GetService(typeof(MyType));

for (var i = 0; i <= obj.NumberOfInstances; i++)
{
    var obj = _kernel.GetService(typeof(MyType));
    ...
}

最后一件真正使它變得混亂的事情; 我們使用Ninject約定將實現綁定到基礎:var assembly = AppDomain.CurrentDomain.GetAssemblies();

this.Bind(x => x
      .From(assemblies)
      .SelectAllClasses()
      .InheritedFrom<BaseMyType>()
      .BindAllBaseClasses());

我希望能夠使用的實現是這樣的:

this.Bind(x => x
      .From(assemblies)
      .SelectAllClasses()
      .InheritedFrom<BaseMyType>()
      .BindAllBaseClasses()
        .Configure(syntax => syntax.InMultipleScope()));

但這可能或不可能或不是一個好主意...

有人做過這樣的事情嗎? 也許您可以看到一種不同的方式?

需求上的詳細信息:我們在單個Azure Worker角色中創建多個線程,這將有利於運行同一代碼的多個副本。

您要的,所以我要給您這個非常臭的丑陋代碼;-)

using System;
using System.Collections.Generic;
using FluentAssertions;
using Ninject;
using Ninject.Extensions.Conventions;
using Ninject.Extensions.Conventions.BindingGenerators;
using Ninject.Syntax;
using Xunit;

public class MultiBaseBindingGenerator : IBindingGenerator
{
    public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
    {
        for (int i = 0; i < 10; i++)
        {
            yield return bindingRoot.Bind(type.BaseType).To(type);
        }
    }
}

public abstract class Foo
{
}

public class SomeFoo : Foo
{
}

public class SomeFooUser
{
    public IEnumerable<Foo> Foos { get; set; }

    public SomeFooUser(IEnumerable<Foo> foos)
    {
        this.Foos = foos;
    }
}

public class Demo
{
    [Fact]
    public void FactMethodName()
    {
        var kernel = new StandardKernel();

        kernel.Bind(x => x.FromThisAssembly()
            .SelectAllClasses()
            .InheritedFrom<Foo>()
            .BindWith<MultiBaseBindingGenerator>());

        kernel.Get<SomeFooUser>().Foos.Should().HaveCount(10);
    }
}

每次插入IEnumerable<Foo>時,這將創建10個Foo實例。 您可以通過將屬性放在類型上並讀取IBindingGenerator來使實例計數可配置。 但是,只能在創建綁定時或之前讀取配置。


還有其他幾種可能性可以達到相同的目標。 我建議僅創建一個綁定-就像您現在所做的那樣。 創建一個工廠IEnumerable CreateMultipleAsConfigured(),該工廠創建所需數量的實例。


另一種可能性是創建自己的集合類型:

public class MultipleAsConfigured<T> : Collection<T> { }

並使用提供程序將其綁定:

IBindingRoot.Bind(typeof(MultipleAsConfigured<>).ToProvider(typeof(MultipleAsConfiguredProvider));   

並讓提供程序讀取配置,實例化所需數量的對象(使用IContext.Get()),創建MultipleAsConfigured並添加項...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM