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

时间:2013-05-24 18:58:46

标签: c# dependency-injection extension-methods service-locator

我正在寻找一种干净的模式来在.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传递给方法的更直接的解决方案?如果可能的话,我想继续使用扩展程序。

3 个答案:

答案 0 :(得分:8)

在Mark Seemann的“.NET中的依赖注入”一书中, 在第2章中,他谈到了4种不同的注射模式:

  1. 构造函数注入
  2. 物业注入
  3. 方法注入
  4. 环境背景
  5. 第四个,Ambient Context,是一个静态属性,可以是抽象类型。 可以在DI Root,线程上下文,调用上下文,请求上下文等中设置此属性。 .NET安全,交易和其他类似的东西都使用这种模式。

    以下链接将为您提供更多详细信息:

    以下是一些示例代码:

    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();
        }
    }
    

答案 1 :(得分:3)

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

所以解决方法是:不要对任何依赖于它自己的东西使用扩展方法:为此编写适当的类和抽象。

答案 2 :(得分:0)

一种可能的解决方案是改为使扩展方法扩展您尝试注入的类,并在上游上下文中引用该依赖项,例如控制器操作或引导的任何其他非静态入口点这个电话。