I am writing a list of filters as a chain and each filter has the next link in its constructor so if a certain chain link can't handle the request it passes it along until it can.
public class SomeFilter : ISomeFilter<ForSomeClass>
{
private readonly ISomeFilter<ForSomeClass> _next;
public SomeFilter(ISomeFilter<ForSomeClass> next)
{
_next = next;
}
public bool IsRelevant()
{
// try to handle it
return _next?.IsRelevant(args) ?? false;
}
}
This is how I registered:
container.Register(Classes.FromAssemblyContaining<ForSomeClass>()
.BasedOn(typeof(ISomeFilter<>))
.WithServiceAllInterfaces()
.LifestyleTransient());
I have encountered two problems:
- When I get to the the last part of the chain that I registered, it loops back to the first one but I want it to stop. I currently thought of these solutions but none of them are good:
- The last chain of the link should not have a next - but this creates a problem, if somebody wants to add another last link they will need to understand that this is the last part of the link and correct the other class, this breaks the single responsibility.
- Implement a null object implementation and inject that always at the end. - Its a whole implementation just to stop a loop.
- Inject a null as the implementation - The IoC doesn't support this.
- I can't order the implementations so they get injected in the order I want. The only way I found I can do it is to literally register them one by one but I have 17 filters and I have register each of them and remember the order of them all and see where the last of them by generic type are. Its very tedious.
Anyone got any suggestions to these 2 problems? How to register the implementations to solve these 2 problems?