Register all classes from base on up in Castle Win

2019-05-29 04:59发布

问题:

I have an abstract base class Search. An abstract class IndexedRepositorySearch descends from Search. An abstract class FacetSearch descends from IndexedRepositorySearch. Concrete classes IngredientFacetSearch and RecipeFacetSearch descend from FacetSearch.

Currently we're registering everything that descends from Search with Castle Windsor as follows:

AllTypes.FromAssembly(assembly)
        .BasedOn<Search.Search>()
        .WithServiceBase()
        .WithServiceSelf()
        .LifestyleTransient()
        .AllowMultipleMatches()

When we then call

_container.ResolveAll<FacetSearch>(new { searchInput = input, searchResults });

It does not resolve anything from the container. When I put a breakpoint on the container after everything has been registered and check AllComponents in the debugger, I see both IngredientFacetSearch and RecipeFacetSearch, but they each only have two Services associated with them: their self and Search, their base. Which you would expect given that they registered with .WithServiceBase() and .WithServiceSelf().

So the question is how to get them to resolve by calling ResolveAll<FacetSearch>()?

I'm sure it's something simple but I'll be darned if I can find it.

Thanks in advance.

回答1:

We had a simliar problem to this, but only needed to register the first base which was abstract. I solved it using WithServiceSelect but wrapped it up into an extension method to be used so:

AllTypes.FromAssembly(assembly)
        .BasedOn<Search.Search>()
        .WithServiceLastAbstractBase(),

The definition of the extension method is:

public static BasedOnDescriptor WithServiceLastAbstractBase(this BasedOnDescriptor basedOn)
{
    return basedOn.WithServiceSelect(selectLastAbstractBase);
}

private static IEnumerable<Type> selectLastAbstractBase(Type type, Type[] basetypes)
{
    var baseType = type;

    do
    {
        baseType = baseType.BaseType;
    } while (baseType != null && !baseType.IsAbstract);

    if (baseType == null)
    {
        throw new ArgumentException("There are no abstract base types for: " + type);
    }

    return new [] { baseType };
}