2011-12-22 78 views
1

免责声明:我对DI和IoC相当陌生,请原谅任何激烈的误解。提供Ninject与构造函数依赖它不能解决?

考虑一个ClassB,它需要一个实现IClassA的对象。 Ninject应该能够注入的ClassA情况下进入ClassB构造,假设它可以构建的ClassA实例:

public class ClassA : IClassA 
{ 
    public ClassA(string runtimeDependency) { /* ... */ } 
} 

public class ClassB : IClassB 
{ 
    public ClassB(IClassA depA) { /* ... */ } 
} 

public sealed class TestBootstrapModule : NinjectModule 
{ 
    public override void Load() 
    { 
     Bind<IClassA>().To<ClassA>(); 
     Bind<IClassB>().To<ClassB>(); 
    } 
} 

现在,让我们说一些运行时的逻辑参与获得提供给ClassAstring runtimeDependency。我应该如何向Ninject提供runtimeDependency,以便它可以提供ClassB的实例ClassA

该字符串只会被确定一次,所以我不需要担心为每个实例注入新值。

回答

2

一个方式这样做是通过一种方法提供ClassA。另外请记住,使用Ninject 2,您不需要模块,并且可以直接在内核中执行绑定。

Bind<IClassA>().ToMethod(_ => 
    { 
    // do something interesting with a runtimeDependancy 
    return new ClassA(someInterestingVariable); 
    }); 

我真的采取了刺来当你运行时变量可用,它的范围。

+0

我很高兴你提到变量的生命期和范围;如果变量在绑定时不存在,该怎么办? (我相信我应该尽早初始化我的所有绑定并在一个共同的位置。) – Rob 2011-12-29 02:49:36

+1

@robjb:这似乎更像是一个设计问题,而不是一个ninject。没有更多的上下文,这很难说。你只需要确定一次字符串,所以它很可能需要你在设置之后做* all *你的绑定。请记住,我绝不是Ninject的专家。 – Marc 2012-01-02 14:05:38

0

这里有几个选项取决于您的设计和具体问题。首先,最简单的解决方法就是提供价值,当你从Ninject

Kernel.Get<IClassA>("runtimeDependencyValue"); 

请求您的服务。然而,如果事情变得更加有趣,这是不可能的。我之前解决这个问题的方法是实际创建System.String本身的上下文绑定。

说,如果我要绑定一个连接字符串,我将创建一个自定义属性:

[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)] 
public class ConnectionStringAttribute : Attribute  
{ 
    /// <summary> 
    /// Denotes the setting that you want to populate the given property with. 
    /// </summary> 
    public string SettingName { get; private set; } 

    public ConnectionStringAttribute(string configSettingName = "") 
    { 
     SettingName = configSettingName; 
    } 
} 

,然后我装饰我的服务的构造是这样的:

public class ClassA : IClassA 
{ 
    public ClassA([ConnectionString("AppDB")] string runtimeDependency) { /* ... */ } 
} 

最后,我结合将看起来像这样:

Bind<string>() 
    .ToMethod(ctx => 
    { 
     var attr = (ConnectionStringAttribute)context.Request.Target.GetCustomAttributes(typeof(ConnectionStringAttribute), true).First(); 
     string settingName = string.IsNullOrEmpty(attr.SettingName) ? context.Request.Target.Name : attr.SettingName; 
     return ConfigurationManager.ConnectionStrings[settingName].ConnectionString; 
    }) 
    .WhenTargetHas<ConnectionStringAttribute>(); 

你明白了。希望这有助于:)