Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 缓存依赖项,还是在注入时复制它们?_C#_Dependency Injection_Automapper_Autofac - Fatal编程技术网

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

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

我有一些由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();
但是,这些对象可以在以后修改(有意或无意),因为它们是单例的,如果发生这种情况,整个应用程序都会受到影响

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

我考虑了两种可能性:

  • 要求Autofac注入对象的“副本”,而不是相同的实例,但我认为其中没有这样的“缓存/副本”功能,我将失去操纵单例的能力,或者
  • 使用Automapper在对象被注入时深度复制对象,并将副本存储在从属对象而不是原始对象中。我对automapper很满意(对象非常轻,所以性能不会有问题),但是为每个注入的属性添加副本会增加Autofac配置的负担,或者会增加对象本身的负担,具体取决于我放置“复制此对象”代码的位置
要使用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()
.带参数(
新解析参数(
(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当然,但它仍然会添加一些代码来维护应用相同逻辑的所有类。