You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ninject中注册两个同接口同类型的单例实例并区分?

嘿,我之前刚解决过一模一样的问题!你现在的写法会让Ninject直接覆盖第一个绑定,最后只会得到一个单例实例——毕竟它没法区分这两个绑定嘛。要实现两个独立的IManifest单例还能精准获取,有几个实用的方法:

方法1:命名绑定(最常用)

这是Ninject里区分同接口多实例最直接的方式,给每个绑定起个唯一的名字就行:

// 注册第一个命名单例
kernel.Bind<IManifest>().To<Manifest>().InSingletonScope().Named("FirstManifest");
// 注册第二个命名单例
kernel.Bind<IManifest>().To<Manifest>().InSingletonScope().Named("SecondManifest");

怎么获取对应实例?

  • 构造函数注入:用[Named]属性标记参数,指定对应的名字:
    public class YourService
    {
        public YourService(
            [Named("FirstManifest")] IManifest firstManifest,
            [Named("SecondManifest")] IManifest secondManifest
        )
        {
            // 这里就能拿到两个不同的单例啦
        }
    }
    
  • 手动解析:直接在Get方法里传入名字:
    var firstInstance = kernel.Get<IManifest>("FirstManifest");
    var secondInstance = kernel.Get<IManifest>("SecondManifest");
    

方法2:自定义属性标记(更类型安全)

如果怕打错字符串名字,可以自定义一个属性来标记,避免拼写错误:

首先定义属性:

public class ManifestKeyAttribute : Attribute
{
    public string Key { get; }
    public ManifestKeyAttribute(string key) => Key = key;
}

然后注册时通过属性过滤:

kernel.Bind<IManifest>()
      .To<Manifest>()
      .InSingletonScope()
      .WithAttributeFilter<ManifestKeyAttribute>(attr => attr.Key == "Primary");

kernel.Bind<IManifest>()
      .To<Manifest>()
      .InSingletonScope()
      .WithAttributeFilter<ManifestKeyAttribute>(attr => attr.Key == "Secondary");

注入时用自定义属性标记参数:

public class YourService
{
    public YourService(
        [ManifestKey("Primary")] IManifest primaryManifest,
        [ManifestKey("Secondary")] IManifest secondaryManifest
    )
    {
        // 同样能拿到两个独立单例
    }
}

方法3:通过构造参数区分(如果实例初始化逻辑不同)

如果你的Manifest类需要不同的构造参数来初始化(比如不同的配置路径),可以通过构造参数来区分绑定:

假设Manifest的构造函数是这样的:

public class Manifest : IManifest
{
    public Manifest(string configFilePath)
    {
        // 根据传入的路径加载配置
    }
}

注册时指定不同的构造参数:

kernel.Bind<IManifest>()
      .To<Manifest>()
      .InSingletonScope()
      .WithConstructorArgument("configFilePath", "configs/first-manifest.json");

kernel.Bind<IManifest>()
      .To<Manifest>()
      .InSingletonScope()
      .WithConstructorArgument("configFilePath", "configs/second-manifest.json");

之后解析时,Ninject会根据你传入的构造参数匹配对应的单例:

var firstInstance = kernel.Get<IManifest>(new ConstructorArgument("configFilePath", "configs/first-manifest.json"));

小提示

如果只是需要简单区分两个实例,命名绑定绝对是最快上手的方案。要是怕字符串拼写错误,可以把名字定义成常量,比如:

public static class ManifestNames
{
    public const string First = "FirstManifest";
    public const string Second = "SecondManifest";
}

这样注册和注入时直接用ManifestNames.First就不会出错啦!

内容的提问来源于stack exchange,提问作者nari447

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:02:13