繁体   English   中英

通用/继承的设计问题

[英]Design issue with generic/inheritance

我找不到解决我面临的设计问题的好方法。 目前,我正在设计一个应该解析查询字符串的系统。

每个解析器都必须实现IQueryParser接口:

public interface IQueryParser
{
    Query Parse();
}

当我收到一个HTTP请求时,我尝试找到一个能够使用工厂进行解析的解析器。 QueryContext只是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();
}

解析器可能需要额外的依赖关系,我不知道如何将它们注入解析器。 假设我们有以下解析器。我如何知道需要IOperatorParser的具体实现?

public class QueryParser : IQueryParser
{
    private readonly QueryContext _context;

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

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

我需要某种依赖注入。 问题是我自己实例化了对象,并且还在运行时传递了QueryContext。 关于如何重新设计应用程序以处理用例的任何提示/想法?

谢谢塞巴斯蒂安

如评论中所述, QueryContext context是运行时数据,不应注入到您的对象中。

您可以使用您提到的CanParse解决方案,也可以使用以下替代方法:

public interface IQueryParser
{
    Maybe<Query> Parse(QueryContext context);
}

Maybe<T>结构用于支持返回值“ no value”(这比返回null Query “ no value”更容易理解和诚实)。 在此处查看更多信息: http : //enterprisecraftsmanship.com/2015/03/13/functional-c-non-nullable-reference-types/

如果该接口的实现无法解析,则应返回“无值”。

现在,消费者得到了一个已经建立的无状态解析器的集合,如下所示:

public class Consumer
{
    private readonly IQueryParser[] parsers;

    public Consumer(IQueryParser[] parsers)
    {
        //..
    }
}

并且每次调用它时,它都会尝试所有解析器,直到找到可以解析查询的解析器为止:

var result =
    parsers
        .Select(x => x.Parse(context))
        .FirstOrDefault(x => x.HasValue); //the default of the `Maybe` struct is a "no value"

if(result.HasValue) //some parse was able to parse
   //...
else
   //..

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM