【问题标题】:SimpleInjector Lazy in a ReflectionSimpleInjector 延迟反射
【发布时间】:2020-05-28 13:59:58
【问题描述】:

我们使用SimpleInjector 作为依赖注入器,并且我们正在使用程序集迭代注册所有接口类型。

public static void RegisterInterfaceTypes(this Container container, Assembly assembly)
{
    assembly.GetExportedTypes()
        .Select(t => new {
            Type = t,
            Interface = t.GetInterfaces().FirstOrDefault()
        })
        .ToList()
        .ForEach(t =>
        {
            container.Register(t.Interface, t.Type, Lifestyle.Transient);
        });
}

我们也有惰性类要注册。我们可以像下面这样一一注册这些类。但是我们想使用反射注册所有具有相似迭代的惰性类型。

container.Register(() => new Lazy<ICommonBusiness>(container.GetInstance<CommonBusiness>));

【问题讨论】:

    标签: c# .net reflection lazy-loading simple-injector


    【解决方案1】:

    您可以使用ResolveUnregisteredType 扩展方法进行最后一分钟注册以解决Lazy&lt;T&gt; 依赖项:

    Source

    public static void AllowResolvingLazyFactories(this Container container)
    {
        container.ResolveUnregisteredType += (sender, e) =>
        {
            if (e.UnregisteredServiceType.IsGenericType &&
                e.UnregisteredServiceType.GetGenericTypeDefinition() == typeof(Lazy<>))
            {
                Type serviceType = e.UnregisteredServiceType.GetGenericArguments()[0];
    
                InstanceProducer registration = container.GetRegistration(serviceType, true);
    
                Type funcType = typeof(Func<>).MakeGenericType(serviceType);
                Type lazyType = typeof(Lazy<>).MakeGenericType(serviceType);
    
                var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile();
    
                var lazyConstructor = (
                    from ctor in lazyType.GetConstructors()
                    where ctor.GetParameters().Length == 1
                    where ctor.GetParameters()[0].ParameterType == funcType
                    select ctor)
                    .Single();
    
                var expression = Expression.New(lazyConstructor, Expression.Constant(factoryDelegate));
    
                var lazyRegistration = registration.Lifestyle.CreateRegistration(
                    serviceType: lazyType,
                    instanceCreator: Expression.Lambda<Func<object>>(expression).Compile(),
                    container: container);
    
                e.Register(lazyRegistration);
            }
        };
    }
    

    用法:

    container.AllowResolvingLazyFactories();
    

    但请注意文档中的the warnings

    警告:默认注册 [Lazy&lt;T&gt;] 是一种设计味道。使用 [Lazy&lt;T&gt;] 会使您的设计更难遵循,并且您的系统更难维护和测试。您的系统最多应该只有其中的几个 [...]。如果您的系统中有许多依赖于 [Lazy&lt;T&gt;] 的构造函数,请仔细查看您的依赖策略。 following article 详细说明了为什么 [这是] 设计气味。

    警告:[...] 组件的构造函数应该简单、可靠且快速(如 Mark Seemann 的 this 博客文章中所述)。这将消除对延迟初始化的需要。有关创建可以成功验证的应用程序和容器配置的更多信息,请阅读How To Verify 容器的配置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-07
      • 2019-08-27
      • 2020-10-12
      • 2016-01-10
      • 2014-05-17
      • 1970-01-01
      • 2020-05-05
      • 1970-01-01
      相关资源
      最近更新 更多