Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.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
.net 装饰器未应用于RegisterAll中指定的实现类型_.net_Simple Injector - Fatal编程技术网

.net 装饰器未应用于RegisterAll中指定的实现类型

.net 装饰器未应用于RegisterAll中指定的实现类型,.net,simple-injector,.net,Simple Injector,在此代码中: container.Register<IDataHoldingSession<DbContext>, EntityFrameworkSession>(); container.RegisterAll<ISession>(typeof(IDataHoldingSession<DbContext>)); container.RegisterDecorator(typeof(IDataHoldingSession<>), typ

在此代码中:

container.Register<IDataHoldingSession<DbContext>, EntityFrameworkSession>();
container.RegisterAll<ISession>(typeof(IDataHoldingSession<DbContext>));
container.RegisterDecorator(typeof(IDataHoldingSession<>), typeof(ValidatingSession<>));
container.Register();
集装箱登记(IDataHoldingsSession类型);
container.RegisterDecorator(typeof(IDataHoldingSession)、typeof(ValidatingSession));
当容器被要求使用
IEnumerable
时,它会得到一个包含
EntityFrameworkSession
的集合,但没有应用装饰程序。如何使其在上述代码中应用decorator


我相信这是因为容器没有被要求
IEnumerable
。我将
registeral
的XML文档解释为,在这种情况下,容器将被要求提供
IDataHoldingSession
的实例,我认为这将导致应用装饰程序。但是,在这种情况下,装饰器似乎被绕过了,因为
registeral
是用
ISession
服务类型调用的。

我能够通过向
registeral
提供
注册来解决这个问题。我将每个注册的服务类型设置为其特定的服务类型,而不是
ISession

下面是一个扩展方法,演示了这一点:

/// <summary>
/// Same as <see cref="Container.RegisterAll"/>, except each implementation service
/// is individually resolved from the container for compatibility with decorators.
/// </summary>
public static void RegisterAllBugFixed<TService>(this Container container, 
    params Type[] serviceTypes)
{
    var registrations = 
        from serviceType in serviceTypes
        select Lifestyle.Transient.CreateRegistration(
            serviceType,
            () => container.GetInstance(serviceType), 
            container);

    container.RegisterAll(typeof(TService), registrations);
}
//
///与相同,但每个实现服务除外
///从容器中单独解析,以与装饰器兼容。
/// 
公共静态无效注册表alBugFixed(此容器,
参数类型[]服务类型)
{
风险值注册=
从serviceTypes中的serviceType
选择Lifestyle.Transient.CreateRegistration(
服务类型,
()=>container.GetInstance(serviceType),
容器);
集装箱登记(类型(TService),登记);
}

简单喷油器中的注册包含两部分:

  • InstanceProducer
    。这是生成实例并负责拦截和装饰实例的对象。
    InstanceProducer
    不知道注册的
    t实现
    ,只知道
    t服务
  • InstanceProducer
    包装
    注册
    对象。此对象负责构建一个表达式,该表达式创建实例,进行构造函数注入、属性注入、自定义初始化,并将生活方式应用于表达式。
    注册
    (仅限)了解
    t实施
  • 进行
    RegisterAll
    注册时,您提供的类型引用了容器中进行的其他注册。您可以通过执行
    Register
    和在
    RegisterAll
    注册中使用该接口类型来实现这一点

    RegisterAll
    在封面下所做的是查询容器以获得给定类型的注册(在您的案例中是
    IDataHoldingSession
    )。因为请求的类型可能与集合的服务类型不同(通常是这样,在您的情况下也是这样)容器从找到的
    InstanceProducer
    中获取
    注册
    ,并基于该
    注册
    创建一个新的
    InstanceProducer
    ,该注册具有集合的实际服务类型。这在简单注入器源代码(在
    ContainerControlledCollection
    中)中如下所示:

    但是由于装饰器是由
    InstanceProducer
    应用的,因此我们将丢失您应用于
    IDataHoldingSession
    的装饰器

    坦率地说,我不知道我们为什么要实现这样的行为,因为最直观的行为会让
    IDataHoldingSession
    的decorator仍然被应用。我认为我们试图防止装饰师被使用两次;这是Simple Injector早期版本中的一个问题

    我将尝试研究这一点,看看是否可以为v2.4提供修复,但我只能在不引入突破性更改的情况下才能做到这一点。同时,我认为你找到的解决方法非常好。如果我进行了修复,我可能会像您现在所做的那样在内部实现它

    很抱歉,简单的喷油器没有按您预期的方式工作

    更新:

    我刚刚在修复的主分支中签入了一个bug修复。包含此修复程序的

    return new InstanceProducer(typeof(TService), instanceProducer.Registration);