I'm looking for a clean pattern to use dependencies in .Net extension methods without explicitly newing-up or using a service locator:
public static class HttpContextExtensions
{
public static SomeClass ExtensionMethod(this HttpContext context)
{
//looking to avoid this
var dependency = ServiceLocator.GetService<DependencyType>();
return dependency.DoSomething(context);
}
}
Am I barking up the wrong tree here? Should I be looking for a more direct solution that passes context
into a method? I'd like to continue using an extension if possible.
The main difference is how the dependencies are located, in Service Locator, client code request the dependencies, in DI Container we use a container to create all of objects and it injects dependency as constructor parameters (or properties). Dependency Injection doesn't require the use of a DI Container though.
Service Locator is a dangerous pattern because it almost works. You can locate Dependencies from consuming classes, and you can replace those Dependencies with different implementations — even with Test Doubles from unit tests.
ASP.NET Core supports the dependency injection (DI) software design pattern, which is a technique for achieving Inversion of Control (IoC) between classes and their dependencies. For more information specific to dependency injection within MVC controllers, see Dependency injection into controllers in ASP.NET Core.
In the book "Dependency Injection in .NET" by Mark Seemann, in chapter 2 he talks about 4 different patterns of injection:
The 4th one, Ambient Context, is a static property, which can be of an abstract type. This property can be set in the DI Root, thread context, call context, request context, etc. .NET Security, Transactions and other stuff like that use this pattern.
Here are links that will give you more details:
Here is some sample code:
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();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With