如何在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
相关产品推荐
相关产品推荐

