Dependency injection for extension classes?

2020-08-10 07:40发布

I'm using Microsoft Unity as my IoC container. I have a number of extension classes which adds useful methods to my business objects This is the sort of code I use today:

public static class BusinessObjectExtensions
{
    public static bool CanDoStuff(this BusinessObject obj) 
    {
        var repository = BusinessHost.Resolver.Resolve<IRepository>();
        var args = new EArgument { Name = obj.Name };
        return repository.AMethod(obj.UserName, args);
    }
}

Is there a better way to manage dependency injection for extension classes?

4条回答
来,给爷笑一个
2楼-- · 2020-08-10 08:06

You should actually try to avoid extensionmethods unless they only work on internal data (properties in the class itself), or simple datatypes provided in the method. You should not talk to other dependencies in your extension methods. If you follow this rule, you should not need to inject extension-classes with your IoC at all.

查看更多
我只想做你的唯一
3楼-- · 2020-08-10 08:15

You can easily resolve dependency injection as this is just a static class.

public static class BusinessObjectExtensions
{
    public static IRepository Repository {get; set;}
    public static bool CanDoStuff(this BusinessObject obj)
    {
         var args = new EArgument { Name = obj.Name };
         return Repository.AMethod(obj.UserName, args);
    }
}

and now somewhere in the code

BusinessObjectExtensions.Repository = ...

You decide the best moment to resolve Repository in your code. You can do it after DI is defined, but you must ensure that it is done before the first usage of the extension.

查看更多
Juvenile、少年°
4楼-- · 2020-08-10 08:23

The de facto default way of Dependency Injection by Constructor Injection is not possible for static classes. It would be possible to use Parameter Injection like below, however that is not a very clean way.

public static class BusinessObjectExtensions
{
    public static bool CanDoStuff(this BusinessObject obj, IRepository repository)
    {
        var args = new EArgument { Name = obj.Name };
        return repository.AMethod(obj.UserName, args);
    }
}
查看更多
女痞
5楼-- · 2020-08-10 08:24

Why would you do that?

This raises the coupling in your application to the roof and can be very confusing for your teammates to use the extension method (they'll have to keep in mind to inject the repository each time the method is used).

Instead, create a separate class and use constructor injection to inject the IRepository instance:

public class StuffExecuter    
{
    private readonly IRepository _repository;

    public StuffExecuter(IRepository repository)
    {
        _repository = repository;
    }

    public bool CanExecute(BusinessObject obj)
    {
        _repository.Add(obj.UserName, new EArgument
        {
            Name = obj.Name
        });
    }
}
查看更多
登录 后发表回答