【问题标题】:How to avoid service locator in .net extension methods如何避免 .net 扩展方法中的服务定位器
【发布时间】:2013-05-20 11:06:15
【问题描述】:

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

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢@Steven。这是我的怀疑。我试图避免使用这种模式,并且需要重新访问我创建具有依赖关系的扩展的地方。
    【解决方案2】:

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

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

    第四个,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();
        }
    }
    

    【讨论】:

    • 能否提供一些使用环境上下文的扩展方法示例代码?
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2014-05-26
      • 2015-12-31
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-29
      • 2011-08-09
      相关资源
      最近更新 更多