如何根据最终用户配置值来解析类型? [英] How to Resolve type based on end-user configuration value?

查看:79
本文介绍了如何根据最终用户配置值来解析类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个接口(称为IAcmeService)有多个实现。

  FileSystemAcmeService 
DatabaseAcmeService
NetworkAcmeService

最终用户需要能够选择将使用哪个实现,并保存



目前,我正在配置我的IOC容器(Unity)以使用名称注册所有已知的实现。



$ a
container.RegisterType(的IAcmeService,DatabaseAcmeService)(DatabaseAcmeService)
容器的容器名称(IAcmeService,FileSystemAcmeService) RegisterType(IAcmeService,NetworkAcmeService)(NetworkAcmeService)

为了让用户保存他们的选择具有存储所使用的服务名称的app.config配置部分文件。



为了解决所选的实现,我在Initiali中进行手动解析使用该服务的类的方法。

 私有_service as IAcmeService 
Public Sub Initialize()
_service = container.Resolve(的IAcmeService)(_ config.AcmeServiceName)
End Sub

这似乎不正确,因为我的班级必须知道容器。但我无法想象出另一种方式。



有没有其他方式允许最终用户选择,而不需要知道容器的类?

解决方案

定义和实施抽象工厂是此类型的标准解决方案的问题。如果你原谅我使用C#,你可以这样定义一个IAcmeServiceFactory界面:

  public interface IAcmeServiceFactory 
{
IAcmeService Create(string serviceName);
}

您现在可以编写一个具体的实现,如下所示:

  public class AcmeServiceFactory:IAcmeServiceFactory 
{
private readonly IAcmeService fsService;
private readonly IAcmeService dbService;
private readonly IAcmeService nwService;

public AcmeServiceFactory(IAcmeService fsService,
IAcmeService dbService,IAcmeService nwService)
{
if(fsService == null)
{
throw新的ArgumentNullException(fsService);
}
if(dbService == null)
{
throw new ArgumentNullException(dbService);
}
if(nwService == null)
{
throw new ArgumentNullException(nwService);
}

this.fsService = fsService;
this.dbService = dbService;
this.nwService = nwService;
}

public IAcmeService Create(string serviceName)
{
switch case serviceName
{
casefs:
返回this.fsService;
casedb:
return this.dbService;
casenw:
return this.nwService;
case default:
throw new ArgumentException(serviceName);
}
}
}

- 如果你想要创建任意数量的IAcmeService实例,但是我会把它作为练习留给读者:)



这将需要你使用Unity注册Factory。在您需要基于名称的IAcmeService的任何地方,您将依赖于IAcmeServiceFactory而不是IAcmeService本身。


I have an interface (call it IAcmeService) that has multiple implementations.

FileSystemAcmeService
DatabaseAcmeService
NetworkAcmeService

The end-user needs to be able to select which implementation will be used and also save that selection.

Currently I'm configuring my IOC container (Unity) to register all the known implemenatation with a name.

container.RegisterType(of IAcmeService, FileSystemAcmeService)("FileSystemAcmeService")
container.RegisterType(of IAcmeService, DatabaseAcmeService)("DatabaseAcmeService")
container.RegisterType(of IAcmeService, NetworkAcmeService)("NetworkAcmeService")

To allow the user to save their selection I have app.config configuration section file that stores the chosen service name to use.

To resolve the selected implementation I'm doing a manual Resolve in the Initialize method of the class the uses the service.

Private _service as IAcmeService
Public Sub Initialize()
    _service = container.Resolve(of IAcmeService)(_config.AcmeServiceName)
End Sub

This doesn't seem right because my class has to know about the container. But I can't figure out another way.

Are there other ways to allow end-user selection without the class knowing about the container?

解决方案

Defining and implementing and Abstract Factory is the standard solution to this type of problem. If you will pardon my use of C#, you can define an IAcmeServiceFactory interface like this:

public interface IAcmeServiceFactory
{
    IAcmeService Create(string serviceName);
}

You can now write a concrete implementation like this one:

public class AcmeServiceFactory : IAcmeServiceFactory
{
    private readonly IAcmeService fsService;
    private readonly IAcmeService dbService;
    private readonly IAcmeService nwService;

    public AcmeServiceFactory(IAcmeService fsService,
        IAcmeService dbService, IAcmeService nwService)
    {
        if (fsService == null)
        {
            throw new ArgumentNullException("fsService");
        }
        if (dbService == null)
        {
            throw new ArgumentNullException("dbService");
        }
        if (nwService == null)
        {
            throw new ArgumentNullException("nwService");
        }

        this.fsService = fsService;
        this.dbService = dbService;
        this.nwService = nwService;
    }

    public IAcmeService Create(string serviceName)
    {
        switch case serviceName
        {
            case "fs":
                return this.fsService;
            case "db":
                return this.dbService;
            case "nw":
                return this.nwService;
            case default:
                throw new ArgumentException("serviceName");
        }
    } 
}

You can make it more general-purpose if you want to be able to create an arbitrary number of IAcmeService instances, but I will leave that as an exercise to the reader :)

This will require you to register the Factory with Unity as well. In any place where you need an IAcmeService based on a name, you take a dependency on IAcmeServiceFactory instead of IAcmeService itself.

这篇关于如何根据最终用户配置值来解析类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆