mardi 6 décembre 2016

Design issue with generic/inheritance

I can't find a good solution to solve a design issue i'm facing. Currently I'm designing a system supposed to parse query string.

Each parser must implement the interface IQueryParser:

public interface IQueryParser
{
    Query Parse();
}

When I receive a HTTP request, I try to find a parser able to parse it using a factory. QueryContext is just a simpler version of HttpRequest

public interface IQueryParserFactory
{
    void Register<TQueryParser>(Func<QueryContext, bool> predicate)
        where TQueryParser : IQueryParser;
    IQueryParser Create(QueryContext context);
}

public class QueryParserFactory : IQueryParserFactory
{
    private readonly ConcurrentDictionary<Type, Func<QueryContext, bool>> _parsers = new ConcurrentDictionary<Type, Func<QueryContext, bool>>();

    public void Register<TQueryParser>(Func<QueryContext, bool> predicate)
        where TQueryParser : IQueryParser
        => _parsers.AddOrUpdate(typeof(TQueryParser), predicate, (key, oldValue) => predicate);

    public IQueryParser Create(QueryContext context)
        => (from kpv in _parsers
            where kpv.Value.Invoke(context)
            select (IQueryParser)Activator.CreateInstance(kpv.Key, context)).FirstOrDefault();
}

Parsers may require extra dependencies and I don't know how to inject them into the parser. Let's say we have the following parser.. How can i know what concrete implementation of IOperatorParser do i need?

public class QueryParser : IQueryParser
{
    private readonly QueryContext _context;

    public QueryParser(QueryContext context, IOperatorParser parser)
    {
        _context = context;
    }

    public Query Parse()
    {
        (...)
    }
}

I would need some kind of dependency injection. The problem is that I instantiate object myself and that I also pass the QueryContext at the runtime. Any hint/idea on how i can redesign my app to handle my use case?

Thank you, Sebastien

Aucun commentaire:

Enregistrer un commentaire