开发者

Nested resolution

开发者 https://www.devze.com 2023-02-08 21:40 出处:网络
Say I have: ProductA ProductB ProductScreen ProductAScreen1 : ProductScreen ProductAScreen2 : ProductScreen

Say I have:

ProductA
ProductB

ProductScreen

ProductAScreen1 : ProductScreen
ProductAScreen2 : ProductScreen

ProductBScreen1 : ProductScreen
ProductBScreen2 : ProductScreen

How can I set it up so that I regi开发者_高级运维ster the screens locally to the product? So when I am in ProductA and passing IEnumerable it doesn't resolve ProductB's screens?

I thought this would be achievable using something like the lifetime scope, but it doesn't appear I understood it correctly.


Lifetime scope is used to control instance lifetime. You are talking about controlling selection. For that, you should look at the metadata features in Autofac.

Using metadata, you can "tag" each product screen, indicating which product it belongs to:

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)));

Next, you can take a dependency on a IEnumerable<Lazy<ProductScreen, IProductScreenMetadata>> and resolve screens according to product type:

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

Update: for completeness, here is a simpler solution using the Keyed approach. First, registration is much simpler:

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));

To resolve a collection of keyed services we'll have to take a dependency on the IIndex<,> type:

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

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

Note: for the curious: instead of hardcoding the type registrations, here's how you can do a "by convention" registration:

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);
}
0

精彩评论

暂无评论...
验证码 换一张
取 消