正确实现同一界面的正确方法

时间:2018-05-09 14:46:13

标签: c# interface asp.net-core-2.0

请注意,如果我不需要,我不打算添加其他依赖项。此外,我在搜索解决方案时发现了大部分想法(stackoverflow.com)。

假设我有一个IPrinterRepository接口,我有多个不同的实现。

例如 EpsonRepository实现IPrinterRepository,与CanonRepository,HPRepository和许多其他

一样

所以现在我在 ConfigurationServices 中注册了我的服务,就像这样

services.AddTransient<EpsonRepository>();
services.AddTransient<HPRepository>();
services.AddSingleton<IPrinterRepositoryResolver, PrinterRepositoryResolver>();

- V1 -

现在,我已经在我的数据库中为某个特定用户激活的每个活动打印机保存了一个PRINTER_CODE。 PrinterCode是一类const字符串。

PrinterRepositoryResolver处理正确实现的选择。所以有一种方法只使用switch语句。

public IPrinterRepository GetRepository(string key)
{   
    switch (key)
    {
        case PrinterCode.Epson:
            return (IPrinterRepository)_serviceProvider.GetService(typeof(EpsonRepository));
        case PrinterCode.HP:
            return (IPrinterRepository)_serviceProvider.GetService(typeof(HPRepository));
        default:
            throw new KeyNotFoundException("Sevice not implemented or not supported any more!");
    }
}

- V2 -

或许我可以按类型选择正确的实现,因此我不必使用PRINTER_CODE或维护switch语句。实施例

而不是PRINTER_CODE将DB中的fullName实现保存为字符串,并在需要时使用它来选择正确的实现。

public IPrinterRepository GetRepository(string ImplementationName)
{
    var repoType= Type.GetType(ImplementationName);
    return (IPrinterRepository)_serviceProvider.GetService(repoType);
}

这一切都适用于我的开发环境,但我不知道它是否正常。

就个人而言,我不喜欢这个开关,因为每次添加新的打印机实现时,有人必须维护PrinterCodes和开关。

但是保存一个带有命名空间的长字符串作为选择的关键是某种方式很难看,我觉得可能有更多的缺点我不知道。是否有一些调整或更好的想法,所以我可以正确的方式做到这一点。

1 个答案:

答案 0 :(得分:1)

我会稍微修改一下V1的方式:

避免了获取样板的对象,并且对象类型与V2的名称没有紧密耦合。

public IPrinterRepository GetRepository(string name)
{
    if (!_PrinterTypes.TryGetValue(name, out var type))
        throw new KeyNotFoundException("Sevice not implemented or not supported any more!");

    return _serviceProvider.GetService(type);
}

static readonly Dictionary<string, Type> _PrinterTypes = new Dictionary<string, Type>
{
    [PrinterCode.Epson] = typeof(EpsonRepository),
    [PrinterCode.HP] = typeof(HPRepository)
};