【发布时间】:2021-07-20 11:08:51
【问题描述】:
我正在寻找某种方法来强制检查(当然是运行时)依赖注入服务的正确生命周期注册,在 .Net Core 或更高版本中。
假设我有一个像这样的有状态服务:
public class MyStatefulService
{
private object _state;
}
但是,我可能会错误地将其注册到错误的生命周期:
services.AddTransient<MyStatefulService>();
因此,我不会收到警报,但实际行为并不是我所期望的:服务是在每次请求时创建的,并且不会保留状态。
我想知道是否有办法加强这种模式。例如,如果我可以用这样的属性来装饰类,那就太好了:
[Singleton]
public class MyStatefulService
{
private object _state;
}
此时,可能在启动时或第一次请求时,如果注册不同于AddSingleton(沿其重载),框架应该抛出。
同样,主题可以申请仅临时服务,不应注册为单例。
我想到的唯一解决方案相当幼稚,我不太喜欢:
//line of principle code
public static class MySingletonChecker
{
private static HashSet<Type> _set = new HashSet<Type>();
public static void Validate(Type type)
{
if (_set.Contains(type))
{
throw new Exception();
}
else
{
_set.Add(type);
}
}
}
public class MyStatefulService
{
public MyStatefulService()
{
MySingletonChecker.Validate(this.GetType());
}
private object _state;
}
有没有更好的解决方案、hack 或任何有助于防止错误的方法?
【问题讨论】:
-
所以你是说注册类型时会出错,而用属性装饰类型时不会出错?
-
我写服务,我知道它是否需要单例。这是你要求的吗?
-
我在问“如果你都写,为什么你放属性时可能不会出错?为什么注册类型时容易出错?为什么你需要一个属性(你永远不会出错)来检查你以后没有犯过你在注册时会犯的错误?如果你做这两件事,为什么你在创建课程时会做对,但在注册课程时 5 分钟后会出错?”
-
@CaiusJard 如果我不面对这个问题,我会像你一样思考。首先,我们正在进行的项目使用了近百种服务。其次,有几个人编写/维护这些服务,但通常只有一个人处理注册。第三,许多服务被设计为在其他应用程序中重复使用,在这些应用程序中,注册不能简单地“链接”。我什至可以告诉你第四个原因:服务可能从无状态开始,然后转为有状态。数据库表适配器就是这种情况,在某个时候您决定添加缓存。
-
如何让 ServiceX 从 SingletonService 派生,然后将其切换为从 TransientService 派生,并为您的注册提供遗传辅助方法(有限制),只接受特定类型的对象,这样您就可以得到一个编译器尝试对派生自 TransientService 的类型使用 RegisterSingleton 帮助程序时出错?
标签: c# asp.net-core dependency-injection .net-5