Imagine there is a Customer
class with an instance Load()
method.
When the Load()
method is called, it retrieves order details by e.g.
var orders = Order.GetAll(customerId, ...);
GetAll()
is a static method of the Order
class and the input parameters are fields defined in the Customer
class.
As you can see, Order
is a dependency of the Customer
class, however, I can't just create an IOrder
and inject it there as interfaces can't have static methods.
Therefore, the question is how could I introduce dependency injection in this example?
I don't want to make GetAll()
an instance method since it's a static method and need to keep it that way.
For example, I have used utility classes in my design, most of which just contain static methods.
If you must keep the static method, I would wrap the static calls in a Repository object. interface IOrderRepository { IEnumerable<IOrder> GetAll(customerId, ..); } class OrderRepository : IOrderRepository { IEnumerable<IOrder> GetAll(customerId, ...) { Order. GetAll(customerId,...); // The original static call. } }
You can use dependency injection in a static class using method or property injection. However, you cannot use constructor injection in a static class because the constructor of a static class cannot accept any parameters.
You could use Lazy initialization for any object you need to inject to a static class. This would allow you to pass around static objects that can be shared across running instances and other classes/methods that need to use those objects.
Static dependency is a horror keyword in unit testing. If it's our own code, then we can change it. If static calls are forced by the external library or NuGet package, then we actually cannot get away from it. It will always be there, and the best thing we can do is avoid it.
If you must keep the static method, I would wrap the static calls in a Repository object.
Like this:
interface IOrderRepository {
IEnumerable<IOrder> GetAll(customerId, ..);
}
class OrderRepository : IOrderRepository {
IEnumerable<IOrder> GetAll(customerId, ...)
{
Order.GetAll(customerId,...); // The original static call.
}
}
Now you inject this repository into your Customer
class.
(I'm assuming you're doing this so you can inject fake IOrders at runtime for testing purposes. I should say that in general, static methods are a serious obstacle to testing.)
Seeing as your aggregate root for fetching orders is your customer model I would strongly advise you create a customer repository and inject that to whatever service requires it.
Here is an example:
public class CustomerService
{
private readonly ICustomerRepository _customerRepository;
public CustomerService(ICustomerRepository customerRepository)
{
if (customerRepository == null)
{
throw new ArgumentNullException("customerRepository");
}
_customerRepository = customerRepository;
}
public IEnumerable<IOrder> GetOrdersForCustomerId(int customerId)
{
return _customerRepository.GetOrdersForCustomerId(customerId);
}
}
public interface ICustomerRepository
{
IEnumerable<IOrder> GetOrdersForCustomerId(int customerId);
}
class CustomerRepository : ICustomerRepository
{
public IEnumerable<IOrder> GetOrdersForCustomerId(int customerId)
{
throw new NotImplementedException();
}
}
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