为 Ninject 提供无法解析的构造函数依赖项?

发布于 2024-12-22 10:30:01 字数 861 浏览 1 评论 0原文

免责声明:我对 DI 和 IoC 还很陌生,请原谅任何严重的误解。

考虑一个需要实现 IClassA 的对象的 ClassB。 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 的实例?

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

Disclaimer: I'm quite new to DI and IoC, please forgive any drastic misunderstandings.

Consider a ClassB that requires a object implementing IClassA. Ninject should be able to inject instances of ClassA into the constructor of ClassB, assuming it can construct instances of 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>();
    }
} 

Now, let's say some runtime logic is involved in deriving the string runtimeDependency provided to ClassA. How should I provide Ninject with runtimeDependency so that it can provide ClassB with instances of ClassA?

The string will only be determined once, so I don't need to worry about injecting a new value into each instance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

断念 2024-12-29 10:30:01

一种方法是通过方法提供ClassA。另请记住,使用 Ninject 2,您不需要模块,可以直接在内核中进行绑定。

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

我真的正在尝试确定您的运行时变量何时可用及其作用域。

One way to do it is to provide the ClassA via a method. Also keep in mind that with Ninject 2, you don't need modules and can do bindings directly in the Kernel.

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

I'm really taking a stab as to when your runtime variable is available and it's scope.

大海や 2024-12-29 10:30:01

根据您的设计和具体问题,这里有一些选项。第一个最简单的解决方案是在您向 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>();

您明白了。希望这有帮助:)

There are a few options here depending on your design, and specific problem. The first, easiest solution is to just provide the value when you request your service from Ninject

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

If this is not possible however, things get a bit more interesting. The way I've solved this previously is to actually create contextual bindings to System.String itself.

Say if I want to bind a connection string, I'll create a custom attribute:

[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;
    }
}

and then I decorate my service constructor like this:

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

Finally, my binding will look something like this:

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>();

You get the idea. Hope this helps :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文