缓存依赖项,还是在注入时复制它们?

Caching dependencies, or copy them at injection?

我有一些由 Autofac 初始化的配置对象。 它们的负载很重(读取配置文件、反序列化、验证一些东西、映射匹配的 POCO 对象...)。
但是性能很好,因为注册的对象被声明为.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();

但是,这些对象可以稍后修改(有意或无意),并且由于它们是单例,如果发生这种情况,整个应用程序都会受到影响。

能够更新初始单例本身(以全局覆盖定义的设置)和更新本地副本(以更改已注入设置 class 的对象的行为,但不是整个应用程序)也会很有趣。

我考虑了两种可能:

要使用 Automapper 的想法,我必须做类似的事情:

        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<MyConsumingClass>().As<IMyConsumingClass>();

(之前的代码没有测试,只是为了举例)

如果能就处理此问题的最佳方法提出建议,我将不胜感激。

如评论中所述,由于缺乏其他建议,我最终保留了自己的初始方法,并在创建消费 class 的新实例时使用 Automapper 克隆我的设置对象。 这是服务及其设置对象的示例。 如果您的“设置”对象在其属性中有 classes,请记住也要克隆它们,否则您将只有初始单例的参考副本!为了避免这个陷阱,您还可以使用比 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();
    }
}