带非服务参数的C#依赖注入实现方式是否符合最佳实践咨询
带非服务参数的C#依赖注入实现方式是否符合最佳实践咨询
嘿,不用不好意思,才接触.NET和DI三个月就能写出这样的代码已经很厉害了!先给你吃个定心丸:你现在用的这种工厂委托注册方式,完全是符合最佳实践的,一点问题都没有。
为什么这么说呢?DI容器的核心职责是管理那些它“认识”的服务类型(比如你这里的IAuth),但instanceName是你的业务自定义参数,容器根本不知道该从哪拿到它的值,所以你通过provider.GetRequiredService<IAuth>()手动从容器获取依赖服务,再自己实例化Instance的做法,刚好完美解决了“混合DI服务和自定义参数”的场景需求——既利用了容器的生命周期管理(这里是单例),又能灵活传入自定义的参数。
当然,根据你的实际场景,还有几种可选的方案供你参考:
- 选项模式(适合配置类参数):如果
instanceName是从配置文件里读的固定值,可以把它封装成一个配置类,比如:
然后在注册时:public class InstanceOptions { public string InstanceName { get; set; } }
或者更简洁的,把services.Configure<InstanceOptions>(configuration.GetSection("InstanceSettings")); services.AddSingleton<Instance>(provider => { var options = provider.GetRequiredService<IOptions<InstanceOptions>>().Value; var auth = provider.GetRequiredService<IAuth>(); return new Instance(options.InstanceName, auth); });Instance的构造函数改成依赖IOptions<InstanceOptions>,容器就能直接帮你解析了:
这种方式适合参数是固定配置的场景,不用手动写工厂逻辑。public Instance(IOptions<InstanceOptions> options, IAuth auth) { _instanceName = options.Value.InstanceName; _auth = auth; } - 工厂类模式(适合动态创建多个实例):如果你需要在业务代码里多次创建不同
instanceName的Instance实例,那注册一个工厂类会更解耦:
然后注册工厂:public interface IInstanceFactory { Instance CreateInstance(string instanceName); } public class InstanceFactory : IInstanceFactory { private readonly IAuth _auth; public InstanceFactory(IAuth auth) { _auth = auth; } public Instance CreateInstance(string instanceName) { return new Instance(instanceName, _auth); } }
之后在需要创建services.AddSingleton<IInstanceFactory, InstanceFactory>();Instance的地方,注入IInstanceFactory调用CreateInstance方法就行,这种方式把实例创建的逻辑封装起来,业务代码不用直接和DI容器打交道。
总结一下:你当前的写法完全没问题,是处理这种场景的标准做法之一。具体选哪种方案,看你的实际需求——如果只是注册一个单例实例,当前写法最简洁;如果要动态创建多个实例,工厂类更合适;如果参数是配置项,选项模式更规范。
内容来源于stack exchange
相关产品推荐
相关产品推荐

