如何正确地使用依赖注入管理这种情况

时间:2016-09-03 17:38:47

标签: c# dependency-injection castle-windsor

想象一下,您有一个WebSite,其中每个用户都可以将代码放入一个框中,然后按“搜索”查找有关产品的信息。代码将匹配模式:SHOPNAME-PROGRESSIVENUMBER,例如:EVERYDAYSHOES-002NEWGAMES-005

当用户按“搜索”按钮时,我的代码将:

  1. 识别商店
  2. 获取连接字符串以连接到数据库,这对于每个商店来说都是不同的
  3. 使用该连接字符串在该DB上调用查询。
  4. 我想到的第一件事就是编写类似的东西:

    public interface IProductInformationsProvider
    {
        string GetProductName(int productCode);
    }
    
    public class SQLProductInformationsProvider : IProductInformationsProvider
    {
        ... 
    
        public SQLProductInformationsProvider(
            string connectionString,
            ILogService logService)
        {
            ...
        }
    
        public string GetProductName(int productCode)
        {
            ...
        }
    }
    

    要获得IProductInformationsProvider的等价,我会使用DI容器并执行以下操作:

    ...

    public void SearchButtonHandler(Dictionary<string, string> shopsConnectionStringsMap)
    {
        using (var container = new WindsorContainer())
        {
            container.Register(
                Component.For<ILogService>()
                .ImplementedBy<ConsoleLogService>());
    
            container.Register(
                Component.For<IProductInformationsProvider>()
                .ImplementedBy<SQLProductInformationsProvider>()
                .DependsOn(
                    Dependency.OnValue("connectionString", shopsConnectionStringsMap[parsedShopName]));
    
            var productInformationsProvider = container.Resolve<IProductInformationsProvider>();
            var productName = productInformationsProvider.GetProductName(theCode);
            // Do something with productName
        }
    }
    

    我的问题是:

    1. 注册是好还是坏(以及为什么) - 按下我的按钮时每次点击都会解决?
    2. 如果不好,我怎么能重构这个以使其与DI模式相关?
    3. 对于第二个问题,我的想法是什么:

      1. 只需点击每次按钮调用Resolve覆盖connectionString

      2. 解析所有可能的SQLProductInformationsProvider,将它们缓存在字典中并使用所需的

      3. 从构造函数中删除connectionString并将其放在方法SetConnectionString(string connectionString)上,但在这种情况下,我将不得不担心线程安全问题。

      4. 所有这三个想法都不能让我满意,他们给我的感觉是我误解了一些东西。我错过了什么/如何改变我的观点?

1 个答案:

答案 0 :(得分:2)

我认为的解决方案是:

public interface IProductInformationsProvider
{
    string GetProductName(int productCode);
}

public interface IConnectionStringProvider
{
    string GetConnectionString(string shopName);
}

public class SQLProductInformationsProvider : IProductInformationsProvider
{
    ... 

    public SQLProductInformationsProvider(
        IConnectionStringProvider connectionStringProvider,
        ILogService logService)
    {
        ...
    }

    public string GetProductName(string shopName, int productCode)
    {
        string connectionString = connectionStringProvider.GetConnectionString(shopName);
        ...
    }
}

public void SearchButtonHandler(string shopName, int Code)
{
    // _productInformationsProvider already resolved
    var productName = _productInformationsProvider.GetProductName(shopName, Code);
    // Do something with productName
}