如何避免.net扩展方法中的服务定位器



我正在寻找一种干净的模式来使用。net扩展方法中的依赖关系,而不需要显式地新建或使用服务定位器:

public static class HttpContextExtensions
{
    public static SomeClass ExtensionMethod(this HttpContext context)
    {
        //looking to avoid this
        var dependency = ServiceLocator.GetService<DependencyType>();
        return dependency.DoSomething(context);
    }
}

我是找错对象了吗?我是否应该寻找一个更直接的解决方案,将context传递到方法中?如果可能的话,我想继续使用分机。

在Mark Seemann的《。net中的依赖注入》一书中,在第二章中,他谈到了4种不同的注入模式:

    构造函数注入
  1. 属性注入
  2. 方法注入
  3. <
  4. 环境上下文/gh>

第四个,Ambient Context,是一个静态属性,它可以是一个抽象类型。这个属性可以在DI根、线程上下文、调用上下文、请求上下文等中设置。. net安全、事务和其他类似的东西使用这个模式。



    《The Ambient Context Design Pattern in .NET》作者:The Wandering Glitch
  • 《Ambient Context》作者:Mark Seemann
  • Tim Robert的《The Ambient Context Pattern》
下面是一些示例代码:

public interface IOutput
{
    void Print(Person person);
}
public class ConsoleOutput : IOutput
{
    public void Print(Person person)
    {
        Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
    }
}
public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
public static class SampleContext
{
    public static IOutput Output { get; set; }
}
public static class ExtensionMethods
{
    public static void Print(this Person person)
    {
        SampleContext.Output.Print(person);
    }
}
static class Program
{
    static void Main()
    {
        //You would use your DI framework here
        SampleContext.Output = new ConsoleOutput();
        //Then call the extension method
        var person = new Person()
        {
            FirstName = "Louis-Pierre",
            LastName = "Beaumont"
        };
        person.Print();
    }
}

您不能为此使用扩展方法。扩展方法是静态的,这意味着你不能使用构造函数注入。只有方法注入是一种选择,但这意味着你必须将依赖项作为方法参数传入,这通常很糟糕,因为依赖项通常应该是一个实现细节,但方法注入使依赖项成为契约的一部分,这意味着扩展方法的消费者应该知道这些依赖项(并将它们注入)。

所以解决方案是:不要为任何有依赖关系的东西使用扩展方法:为此编写一个适当的类和抽象。

一种可能的解决方案是让扩展方法扩展您试图注入的类,并在上游上下文中引用该依赖项,例如控制器动作,或导致此调用的任何其他非静态入口点。

相关内容

  • 没有找到相关文章

最新更新