按惯例注册delegate-func

时间:2014-11-28 07:21:27

标签: autofac

ContainerBuilder我可以执行以下操作:

builder.Register<ScenariosConfig>(c =>
            (ScenariosConfig)c.Resolve<ConfigFactory>()
                  .Create(typeof(ScenariosConfig)))
       .SingleInstance();

使用装配扫描我可以执行以下操作:

builder.RegisterAssemblyTypes(assemblies)
    .Where(HasSingletonAttribute)
    .As(t => GetNameMatchingInterfaces(t))
    .SingleInstance();

现在问题:有什么办法可以实现以下目标:?

builder.RegisterAssemblyTypes(assemblies)
       .Where(... some condition)
       .CreateByDelegate((container, type) 
            => c.Resolve<ConfigFactory>().Create(type))
       .SingleInstance();

我已经发现IRegistrationSource可以实现类似的。{但是,对于我需要代表创建的每个约定IRegistrationSource创建吨的性能影响,我有点怀疑...... 而且,当你需要解决IRegistrationSource的所有IFoo实例时,{{1}}无法使用{{1}},而这些实例应受到这样一个&#34;约定的约束。

1 个答案:

答案 0 :(得分:0)

最后我们选择使用IRegistrationSource。我发现的唯一替代方法是检测每次反射的所有类型(不使用autofac API ...),然后为每个类型生成一个委托并使用autofac注册它。真的不会导致代码容易理解......

因此,为了完整起见,这里是IRegistrationSource实现:

public class ConfigConventionRegistrationSource : IRegistrationSource
{
    public IEnumerable<IComponentRegistration> RegistrationsFor(
       Service service,
       Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
    {
        var s = service as IServiceWithType;
        if (s != null
            && s.ServiceType.IsClass
            && s.ServiceType.Name.EndsWith("Config")
            && !s.ServiceType.GetInterfaces().Any())
        {
            yield return RegistrationBuilder
                .ForDelegate((componentContext, parameters) =>
                              CreateConfigByFactory(componentContext, s.ServiceType))
                .As(s.ServiceType)
                .SingleInstance()
                .CreateRegistration();
        }
    }

    private static object CreateConfigByFactory(
                              IComponentContext componentContext, 
                              Type configType)
    {
        IConfig configFactory = componentContext.Resolve<IConfig>();
        MethodInfo method = Reflector<IConfig>
                                        .GetMethod(x => x.Load<object>())
                                        .GetGenericMethodDefinition()
                                        .MakeGenericMethod(configType);
        try
        {
            return method.Invoke(configFactory, new object[0]);
        }
        catch (TargetInvocationException tex)
        {
            ExceptionDispatchInfo
                .Capture(tex.InnerException)
                .Throw();
            throw; // will not be reached as thrown above ;-)
        }
    }

    public bool IsAdapterForIndividualComponents
    {
        get { return false; }
    }
}