0

I am designing a class that uses an abstract property to provide a point of access to a field. Here is a snippet of my code:

public abstract class PageBroker : WebBroker
{
    public abstract IPageProvider Provider { get; }
}

public class ArticleBroker : PageBroker
{
     public override IPageProvider Provider { get; } = new ArticleProvider();
}

I realized I could refactor this to use DI instead, like so:

public class PageBroker : WebBroker
{
    public PageBroker(IPageProvider provider)
    {
        this.Provider = provider;
    }

    public IPageProvider Provider { get; private set; }

    // implementation...
}

// no derived class, just new PageBroker(new ArticleProvider())

In what situation(s) would one technique be appropriate over the other?

James Ko
  • 32,215
  • 30
  • 128
  • 239
  • 1
    Constructor injection should be used when the value is _required_ for the class to function property. Property injection should be used when injecting a value is optional (e.g. there is a default or the property is not needed for the client's specific usage). – D Stanley Jun 10 '15 at 21:14
  • 1
    @DStanley I'm sorry, that was not my question at all. I was asking if I should **make the property `abstract` so a derived class can implement it**, or pass it in through the constructor. This has nothing to do with setter injection. – James Ko Jun 10 '15 at 21:24
  • Well, constructors aren't inherited, so a derived class is going to have to "override" something either way. So I'm not sure what difference you're looking for (other than setter vs constructor injection). – D Stanley Jun 10 '15 at 21:30
  • 1
    @DStanley Thank you, updated question to clarify. (There is no derived class with DI.) – James Ko Jun 10 '15 at 21:36
  • 1
    Personally, I would use the second one because I can use an external resource for providing my `IPageProvider` (pretty much the definition of DI). The use for the first is if I had another justification that `ArticleBroker` needs to differ/inherit from a `PageBroker`. – Kyle Jun 10 '15 at 21:43

3 Answers3

3

This is about favoring composition over inheritance, which is a good guideline. I would suggest that since the PageBroker has an IPageProvider, you should use DI. Users of the class can provide alternate implementations without inheritance, say to inject a test IPageProvider. For this reason alone, I would go with DI.

If there is an existential difference based on IPageProvider such that using a different provider semantically needs to reflect an is a relationship (a subtype of PageBroker), then I would go with an abstract class.

BJ Safdie
  • 3,399
  • 23
  • 23
3

I agree with BJ Safdie's answer.

That said, I think the main difference is that in the first implementation, ArticleBroker is coupled to a specific implementation of IPageProvider (namely ArticleProvider). If this is intended, I see no problem with it. However, if you want to provide an implementation of IPageProvider at runtime (either in production code or in a unit test via mocks/fakes), then injecting the dependency is the better choice.

Phil Sandler
  • 27,544
  • 21
  • 86
  • 147
1

As already stated I would populate your Provider with DI. That said what are you looking to gain via the abstract class? If it is simply to inject the IPageProvider then there is really nothing more to say.

If however you have other common methods in mind that are very specific to WebBrokers or PageBrokers then why not use both?

For example:

public abstract class WebBroker
{
    private IPageProvider _pageProvider;

    protected WebBroker(IPageProvider pageProvider)
    {
        _pageProvider = pageProvider;
    }

    public override void CommonThing(int someData)
    {
       var result = _pageProvider.CommonMethod(someData);
       //do something with result
    }
}

Now all your WebBrokers have the CommonThing method which uses the _pageProvider that DI passed in.

PaulBinder
  • 2,022
  • 1
  • 16
  • 26