WCF依赖注入和抽象工厂

19

我有这个WCF方法

Profile GetProfileInfo(string profileType, string profileName)

还有一个业务规则:

如果profileType是“A”,则从数据库中读取。

如果profileType是“B”,则从xml文件中读取。

问题是:如何使用依赖注入容器实现它?

2个回答

24

首先假设您拥有一个类似于以下内容的IProfileRepository:

public interface IProfileRepository
{
     Profile GetProfile(string profileName);
}

除此之外,还有两个实现:DatabaseProfileRepositoryXmlProfileRepository。问题是你想根据profileType的值选择正确的实现。

您可以通过引入这个抽象工厂来实现:

public interface IProfileRepositoryFactory
{
    IProfileRepository Create(string profileType);
}

假设 IProfileRepositoryFactory 已经被注入到服务实现中,现在可以像这样实现 GetProfileInfo 方法:

public Profile GetProfileInfo(string profileType, string profileName)
{
    return this.factory.Create(profileType).GetProfile(profileName);
}

一个IProfileRepositoryFactory的具体实现可能如下所示:

public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
    private readonly IProfileRepository aRepository;
    private readonly IProfileRepository bRepository;

    public ProfileRepositoryFactory(IProfileRepository aRepository,
        IProfileRepository bRepository)
    {
        if(aRepository == null)
        {
            throw new ArgumentNullException("aRepository");
        }
        if(bRepository == null)
        {
            throw new ArgumentNullException("bRepository");
        }

        this.aRepository = aRepository;
        this.bRepository = bRepository;
    }

    public IProfileRepository Create(string profileType)
    {
        if(profileType == "A")
        {
            return this.aRepository;
        }
        if(profileType == "B")
        {
            return this.bRepository;
        }

        // and so on...
    }
}

现在你只需要选择你喜欢的依赖注入容器,让它为你连接所有内容...


3
没错,我没有异议,但我只是按照原帖中提供的API去做了 :) - Mark Seemann
如果我在编译时不知道存储库的数量,该如何更改呢? 如果我的WCF仅依赖于日志库和这些存储库,哪种DI容器是最好的选择?在这种情况下,MEF是一个好的选择吗? - tartafe
你会建议将 ProfileRepositoryFactory 类放在哪个包中?是在组合根(它涉及对象创建),服务层(这是业务规则)还是实际存储库实现旁边? - MEMark
1
@MEMark 这取决于 :) 如果它包含重要的业务逻辑,应该将其放在域模型中,以便可以进行适当的测试,但这也意味着它必须是手动编码工厂; 否则,您可以将其放在组合根中,在这种情况下,您具有较少的实现约束。 - Mark Seemann
为什么不向GetProfile函数添加profileType参数呢? - remi bourgarel
显示剩余3条评论

6
马克的回答很好,但是给出的解决方案不是抽象工厂,而是标准工厂模式的实现。请检查一下马克的类如何适配标准工厂模式UML图。单击此处以查看上述类应用于工厂模式UML 由于在工厂模式中,工厂知道具体的类,因此我们可以将ProfileRepositoryFactory代码简化如下。注入不同的存储库到工厂的问题在于每次添加新的具体类型时您需要进行更多的代码更改。使用以下代码,您只需更新switch以包含新的具体类即可。

    public class ProfileRepositoryFactory : IProfileRepositoryFactory
    {
        public IProfileRepository Create(string profileType)
        {
            switch(profileType)
            {
                case "A":
                    return new DatabaseProfileRepository();
case "B": return new XmlProfileRepository(); } } }

抽象工厂是一种更高级的模式,用于创建相关或依赖对象族,而不指定它们的具体类。这里提供的UML类图 在此处 很好地解释了它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接