嵌套分辨率

时间:2011-02-07 20:07:44

标签: dependency-injection autofac

说我有:

ProductA
ProductB

ProductScreen

ProductAScreen1 : ProductScreen
ProductAScreen2 : ProductScreen

ProductBScreen1 : ProductScreen
ProductBScreen2 : ProductScreen

如何设置它以便我在本地注册产品?因此,当我在ProductA中并传递IEnumerable时,它无法解析ProductB的屏幕?

我认为这可以通过使用寿命范围之类的东西来实现,但似乎我没有理解它。

1 个答案:

答案 0 :(得分:4)

生命周期范围用于控制实例生命周期。你在谈论控制选择。为此,您应该在Autofac中查看the metadata features

使用元数据,您可以“标记”每个产品屏幕,指明它属于哪个产品:

builder.Register(c => new ProductAScreen1()).As<ProductScreen>()
    .WithMetadata<IProductScreenMetadata>(m =>
        m.For(am => am.ProductType, typeof(ProductA)));
builder.Register(c => new ProductAScreen2()).As<ProductScreen>()
    .WithMetadata<IProductScreenMetadata>(m =>
        m.For(am => am.ProductType, typeof(ProductA)));

builder.Register(c => new ProductBScreen1()).As<ProductScreen>()
    .WithMetadata<IProductScreenMetadata>(m =>
        m.For(am => am.ProductType, typeof(ProductB)));
builder.Register(c => new ProductBScreen2()).As<ProductScreen>()
    .WithMetadata<IProductScreenMetadata>(m =>
        m.For(am => am.ProductType, typeof(ProductB)));

接下来,您可以依赖IEnumerable<Lazy<ProductScreen, IProductScreenMetadata>>并根据产品类型解析屏幕:

var productScreens = _screens.WHere(a => a.Metadata.ProductType == typeof(ProductA));

更新:为了完整性,这是使用the Keyed approach的更简单的解决方案。首先,注册要简单得多:

builder.RegisterType<ProductAScreen1>().Keyed<ProductScreen>(typeof(ProductA));
builder.RegisterType<ProductAScreen2>().Keyed<ProductScreen>(typeof(ProductA));
builder.RegisterType<ProductBScreen1>().Keyed<ProductScreen>(typeof(ProductB));
builder.RegisterType<ProductBScreen2>().Keyed<ProductScreen>(typeof(ProductB));

要解析一系列键控服务,我们必须依赖IIndex<,>类型:

public class SomeService    
{
    private IEnumerable<ProductScreen>> _screens;
    public SomeService(IIndex<Type, IEnumerable<ProductScreen>> screens)
    {
        _screens = screens;
    }

    public void DoSomething()
    {
        var screensForProductA = _screens[typeof(ProductA)];
    }
}

注意:对于好奇:不是硬编码类型注册,这里是你如何做“按惯例”注册:

var assembly = ...;
var productTypes = ...;  // a collection of all the product types

foreach(var productType in productTypes)
{
    builder.RegisterAssemblyTypes(assembly)
        .Where(t => typeof(ProductScreen).IsAssignableFrom(t))
        .Where(t => t.Name.StartsWith(productType.Name))
        .Keyed<ProductScreen>(productType);
}