免责声明:我对DI和IoC都很陌生,请原谅任何严重的误解。
考虑一个需要实现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>();
}
}
现在,假设某些运行时逻辑涉及派生到string runtimeDependency
的{{1}}。我应该如何向Ninject提供ClassA
,以便它可以runtimeDependency
提供ClassB
个实例?
字符串只会被确定一次,所以我不必担心在每个实例中注入一个新值。
答案 0 :(得分:2)
执行此操作的方式是通过方法提供ClassA
。还要记住,使用Ninject 2,您不需要模块,可以直接在内核中进行绑定。
Bind<IClassA>().ToMethod(_ =>
{
// do something interesting with a runtimeDependancy
return new ClassA(someInterestingVariable);
});
当你的你的运行时变量可用且它的范围是时,我真的正在努力。
答案 1 :(得分: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>();
你明白了。希望这会有所帮助:)