小编dav*_*off的帖子

ServiceLocator是反模式吗?

最近我读过Mark Seemann关于Service Locator反模式的文章.

作者指出ServiceLocator为反模式的两个主要原因:

  1. API使用问题(我完全可以使用)
    当类使用服务定位器时,很难看到它的依赖关系,因为在大多数情况下,类只有一个PARAMETERLESS构造函数.与ServiceLocator相比,DI方法通过构造函数的参数显式地暴露依赖关系,因此在IntelliSense中很容易看到依赖关系.

  2. 维护问题(让我感到困惑)
    请考虑以下示例

我们有一个使用服务定位器方法的类'MyType':

public class MyType
{
    public void MyMethod()
    {
        var dep1 = Locator.Resolve<IDep1>();
        dep1.DoSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们要为类'MyType'添加另一个依赖项

public class MyType
{
    public void MyMethod()
    {
        var dep1 = Locator.Resolve<IDep1>();
        dep1.DoSomething();

        // new dependency
        var dep2 = Locator.Resolve<IDep2>();
        dep2.DoSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是我的误解开始的地方.作者说:

要判断你是否引入了一个重大改变,要变得更加困难.您需要了解使用Service Locator的整个应用程序,并且编译器不会帮助您.

但是等一下,如果我们使用DI方法,我们将在构造函数中引入与另一个参数的依赖关系(在构造函数注入的情况下).问题仍然存在.如果我们忘记设置ServiceLocator,那么我们可能忘记在IoC容器中添加新的映射,并且DI方法将具有相同的运行时问题.

此外,作者还提到了单元测试的难点.但是,我们不会有DI方法的问题吗?我们不需要更新所有实例化该类的测试吗?我们将更新它们以传递一个新的模拟依赖项,以使我们的测试可编译.我没有看到更新和时间花费带来任何好处.

我不是想捍卫Service Locator方法.但这种误解让我觉得我失去了一些非常重要的东西.有人可以消除我的怀疑吗?

更新(摘要):

我的问题"服务定位器是反模式"的答案实际上取决于具体情况.我绝对不会建议你从工具列表中删除它.当您开始处理遗留代码时,它可能会变得非常方便.如果你很幸运能够处于项目的最初阶段,那么DI方法可能是更好的选择,因为它比Service Locator有一些优势.

以下是主要的不同之处,这些差异使我不相信我的新项目使用Service Locator:

  • 最明显和最重要的是:Service Locator隐藏了类依赖项
  • 如果你正在使用一些IoC容器,它可能会在启动时扫描所有构造函数以验证所有依赖项,并立即给你关于缺失映射(或错误配置)的反馈; 如果您将IoC容器用作服务定位器,则无法进行此操作

有关详细信息,请阅读下面给出的优秀答案.

design-patterns dependency-injection anti-patterns service-locator

127
推荐指数
4
解决办法
3万
查看次数

MVC控制器无法执行Async方法

我有一个非常基本的MVC控制器,只有一个动作:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        OpenConnection().Wait();

        return View();
    }

    private async Task OpenConnection()
    {
        var synchronizationContext = SynchronizationContext.Current;
        Debug.Assert(synchronizationContext != null);

        using (
            var connection =
                new SqlConnection(
                    @"Data Source=(localdb)\ProjectsV12;Initial Catalog=Database1;Integrated Security=True;"))
        {
            await connection.OpenAsync(); // this always hangs up                
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是常规操作(不是异步版本)无法执行异步方法.在我的情况下,OpenConnection()方法总是挂起等待connection.OpenAsync()行.

过了一段时间,我发现了两种使代码正常工作的方法.

  1. 使控制器的操作异步

    public async Task<ActionResult> Index()
    {
        await OpenConnection();
    
        return View();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或者允许异步执行而不捕获原始SychronizationContext - 为此:

    await connection.OpenAsync();

    用...来代替:

    await connection.OpenAsync().ConfigureAwait(false);

所以,我的猜测是我最初的问题是在SynchronizationContext周围.但是SynchronizationContext.Current不是null,这让我想知道我的猜测是否正确.

那么,任何人都可以解释一下,为什么MVC控制器中的异步操作不能同步执行异步方法?

c# task async-await asp.net-mvc-4

9
推荐指数
1
解决办法
1万
查看次数

TFS合并算法问题

我们使用TFS 2010并有三个分支:Dev - > QA - > Production.

在这个特定的例子中,我们决定将方法参数类型和名称从"Guid reportGuid"更改为"int reportId".我们在QA分支中进行了此更改并将其检入.现在我正在尝试将此更改从QA转移到Dev分支.通常它是在相反的方向完成,但在这种特殊情况下,我们做了我们所做的.是合并工具的屏幕截图.从截图中可以看出,Dev分支中文件的最后一次登记获得了更改集号30282和QA-31002(比30282更新).至于我,很明显,新的改变应该覆盖旧的改变.但TFS合并的做法恰恰相反.它将来自Dev分支(30282)的旧代码应用于来自QA分支(31002)的新代码,结果不会得到更改.

有人可以解释为什么TFS合并就是这样吗?提前致谢.

merge tfs tfs2010

2
推荐指数
1
解决办法
3561
查看次数