C# 缓存依赖项,还是在注入时复制它们?
我有一些由Autofac初始化的配置对象。 它们的负载相当重(读取配置文件、反序列化配置文件、验证某些内容、映射匹配的POCO对象……。C# 缓存依赖项,还是在注入时复制它们?,c#,dependency-injection,automapper,autofac,C#,Dependency Injection,Automapper,Autofac,我有一些由Autofac初始化的配置对象。 它们的负载相当重(读取配置文件、反序列化配置文件、验证某些内容、映射匹配的POCO对象……。 但是性能很好,因为注册的对象被声明为.SingleInstance(),所以它只被加载一次,第一次被注入到某个地方,之后总是使用同一个实例 builder.Register(c => _settingsReader.LoadSection(thing)) // Read and map object .OnActi
但是性能很好,因为注册的对象被声明为
.SingleInstance()
,所以它只被加载一次,第一次被注入到某个地方,之后总是使用同一个实例
builder.Register(c => _settingsReader.LoadSection(thing)) // Read and map object
.OnActivated(t =>
{
// Do some checks on it to see if settings appear to be correct
})
.As(settingInterface)
.SingleInstance();
但是,这些对象可以在以后修改(有意或无意),因为它们是单例的,如果发生这种情况,整个应用程序都会受到影响
同时能够更新初始单例本身(全局覆盖已定义的设置)和更新本地副本(更改已注入设置类的对象的行为,但不更改整个应用程序的行为)也很有趣
我考虑了两种可能性:
- 要求Autofac注入对象的“副本”,而不是相同的实例,但我认为其中没有这样的“缓存/副本”功能,我将失去操纵单例的能力,或者
- 使用Automapper在对象被注入时深度复制对象,并将副本存储在从属对象而不是原始对象中。我对automapper很满意(对象非常轻,所以性能不会有问题),但是为每个注入的属性添加副本会增加Autofac配置的负担,或者会增加对象本身的负担,具体取决于我放置“复制此对象”代码的位置
builder.RegisterType<MyConsumingClass>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IMySettingClass),
(pi, ctx) =>
{
var mapper = ctx.Resolve<Mapper>();
return mapper.Map<ConcreteSettingClass>(ctx.Resolve<IMySettingClass>());
}))
.As<IMyConsumingClass>();
builder.RegisterType()
.带参数(
新解析参数(
(pi,ctx)=>pi.ParameterType==typeof(IMySettingClass),
(pi,ctx)=>
{
var mapper=ctx.Resolve();
返回mapper.Map(ctx.Resolve());
}))
.As();
而不仅仅是
builder.RegisterType<MyConsumingClass>().As<IMyConsumingClass>();
builder.RegisterType().As();
(前面的代码还没有经过测试,这里只是举个例子)
我非常希望能就处理这个问题的最佳方法提出建议。如评论中所述,由于缺乏其他建议,我最终保留了自己最初的方法,并在创建消费类的新实例时使用Automapper克隆了我的设置对象。 下面是一个服务及其设置对象的示例。 如果您的“设置”对象的属性中有类,请记住也要克隆它们,否则您将只有初始单例的引用副本!为了避免这个陷阱,您还可以使用比Automapper更适合这种情况的真正的“克隆库”
public class ServiceFacadeModule
: Module
{
protected override void Load(ContainerBuilder builder)
{
// Modifying the settings on the service instance itself should NOT affect global setting object. To achieve this, settings classes are copied when initializing new service instances
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<ServiceSettings, ServiceSettings>();
});
var mapper = new Mapper(config);
builder.RegisterType<ServiceDAO>()
.WithParameter(
new ResolvedParameter(
(pi, _) => pi.ParameterType == typeof(ISettings),
(_, ctx) => mapper.Map<ServiceSettings>(ctx.Resolve<ISettings>())))
.As<IServiceDAO>()
.InstancePerLifetimeScope();
}
}
公共类ServiceFacadeModule
:模块
{
受保护的覆盖无效负载(ContainerBuilder builder)
{
//修改服务实例本身的设置不应影响全局设置对象。为此,在初始化新服务实例时复制设置类
var config=new-MapperConfiguration(cfg=>
{
CreateMap();
});
变量映射器=新映射器(配置);
builder.RegisterType()
.带参数(
新解析参数(
(pi,)=>pi.ParameterType==typeof(ISettings),
(\ux,ctx)=>mapper.Map(ctx.Resolve()))
.As()
.InstancePerLifetimeScope();
}
}
将该类注册为singleton,注册另一个将用作作用域的类。在作用域服务中注入singleton,并使用作用域one从其依赖项克隆配置,并在不影响singleton的情况下修改每个作用域?在我看来,您可以在相关类上设置约束,以便在它们更改时将它们复制到singleton类。您是否考虑过像init
属性这样的东西,以便以后不能更改它?@YegorAndrosov很有意思,但这会迫使必须将类、初始singleton和“holder”分开生命周期有限。@isaid当然,但它仍然会添加一些代码来维护应用相同逻辑的所有类。