【问题标题】:Context variables in Ninject 2Ninject 2 中的上下文变量
【发布时间】:2010-10-20 14:27:21
【问题描述】:

我在早期版本的 Ninject 的上下文变量中找到了this article。我的问题有两个。首先,如何使用 Ninject 2 获得这种行为?其次,上下文变量是否沿着请求链进行?例如,假设我想替换这些调用:

var a = new A(new B(new C())));
var specialA = new A(new B(new SpecialC()));

...用这个:

var a = kernel.Get<A>();
var specialA = kernel.Get<A>(With.Parameters.ContextVariable("special", "true"));

是否可以设置这样的绑定,当需要构造C 时,上下文会记住它处于“特殊”上下文中?

【问题讨论】:

    标签: ninject ninject-2


    【解决方案1】:

    这是我针对 V2 使用的一些东西,为您清理了大约 0 次努力 - 如果您无法解开它,请告诉我。

    正如您所推测的那样,似乎没有一个真正明确的 API 可以按原样显示 v2 中的“上下文参数,即使对于嵌套分辨率”的内容(它的存在作为第三个参数隐藏在Parameterctor)。

    public static class ContextParameter
    {
        public static Parameter Create<T>( T value )
        {
            return new Parameter( value.GetType().FullName, value, true );
        }
    }
    
    public static class ContextParameterFacts
    {
        public class ProductId
        {
            public ProductId( string productId2 )
            {
                Value = productId2;
    
            }
            public string Value { get; set; }
        }
    
        public class Repository
        {
            public Repository( ProductId productId )
            {
                ProductId = productId;
    
            }
            public ProductId ProductId { get; set; }
        }
    
        public class Outer
        {
            public Outer( Repository repository )
            {
                Repository = repository;
            }
            public Repository Repository { get; set; }
        }
    
        public class Module : NinjectModule
        {
            public override void Load()
            {
                Bind<ProductId>().ToContextParameter();
            }
        }
    
        //[ Fact ]
        public static void TwoDeepShouldResolve()
        {
            var k = new StandardKernel( new Module() );
            var o = k.Get<Outer>( ContextParameter.Create( new ProductId( "a" ) ) );
            Debug.Assert( "a" == o.Repository.ProductId.Value );
        }
    }
    

    这里有一些代码[会混淆问题],它演示了我如何在我的上下文中应用它:-

    public class ServicesNinjectModule : NinjectModule
    {
        public override void Load()
        {
            Bind<ProductId>().ToContextParameter();
    
            Bind<Func<ProductId, ResourceAllocator>>().ToConstant( ( productId ) => Kernel.Get<ResourceAllocator>(
                ContextParameter.Create( productId ) ) );
        }
    }
    
    public static class NinjectContextParameterExtensions
    {
        public static IBindingWhenInNamedWithOrOnSyntax<T> ToContextParameter<T>( this IBindingToSyntax<T> bindingToSyntax )
        {
            return bindingToSyntax.ToMethod( context => (T)context.Parameters.Single( parameter => parameter.Name == typeof( T ).FullName ).GetValue( context ) );
        }
    }
    

    像往常一样,你应该去看看源代码和测试——他们会为你提供比我更详细和相关的答案。

    【讨论】:

    • 您可能还会发现这很有用:stackoverflow.com/questions/1374098/…
    • 这真是很棒的东西,我可以用它来非常接近我需要的东西。不幸的是,每当我绑定到提供者或方法时,“继承”参数都会丢失。我可以使用一些技巧来确保方法将参数向下传递,但这将成为一个复杂和重复的点。我想我最终会为我们系统中的每个上下文使用不同的内核。感谢您的回复。
    • @StriplingWarrior:很高兴它有帮助。顺便说一句,我认为有一些方法和方法可以让您像您所说的那样在工厂中传播上下文(您是否使用上下文参数来做到这一点?即 context.Get 而不是 _kernel.Get ?测试表明了这一点。认真地去看看测试,你会怀疑它。如果你有一个简短的问题,我该如何干净利落地把这个和那个挂钩,然后在这里问我或像@Ian Davis 这样的人。
    • 我找不到context.Get&lt;X&gt; 方法。你能指出我所指的测试吗?我总是不得不做 context.Kernel.Get,所以我必须手动将 ShouldInherit 参数从上下文中拉出并传递它们。当我尝试绑定到提供者时,创建并提供给提供者的对象不是使用我提供的绑定参数创建的。这对我来说似乎是一个错误。无论如何,我通过创建具有与根内核相同模块的新内核然后覆盖某些绑定来使其工作。
    • @StriplingWarrior:我在猜测执行 context.Get 的确切方式,但我知道有一种通用机制来处理嵌套激活。下载完整的后备箱,为 ShouldInherit 执行 Find In Files,你应该是金子了。 (我有一两个月没有看过源代码,所以这在我脑海中并不新鲜——但我知道一个事实,如果你尝试一下,你会在 5 分钟内搞定它——代码和测试和你一样干净会找到的。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多