Please see the code below (contained in an IEnumerable method):
int Quantity = (int)Math.Floor(ChangeRequired / CurrencyAmount);
ChangeDenomination = ChangeDenominationsFactory.Create(CurrencyAmount, Quantity);
yield return ChangeDenomination;
ChangeRequired = ChangeRequired - (ChangeDenomination.Amount * ChangeDenomination.Quantity);
ChangeDenominationsFactory and ChangeDenomination are injected into the constructor.
As you can see the ChangeDenomination class has a zero arguments constructor - it is immutable.
I am using Castle Windsor. There are two ways I can set this up:
1) Introduce a zero arguments constructor into ChangeDenomination specifically for Castle Windsor. 2) Configure Castle Windsor so that ChangeDenomination is given the necessary arguments as follows:
Component.For<IDenomination, Denomination>().DependsOn(Dependency.OnValue("amount", 0.0M), Dependency.OnValue("quantity", 0))
Both approaches work as expected. Which way is "best practice".
-
Can you explain why you need a factory and injection? That seems to be a lot of overhead for a small, immutable object. Why not just ` = new ChangeDenomination(CurrencyAmount, Quantity);`?nvoigt– nvoigt2017年06月15日 15:16:54 +00:00Commented Jun 15, 2017 at 15:16
-
And why does your DIC know about the concrete class, when it also provides a factory, so you don't need to know the actual class?nvoigt– nvoigt2017年06月15日 15:18:44 +00:00Commented Jun 15, 2017 at 15:18
-
Which approach makes the most sense for you and your specific situation? See also meta.stackexchange.com/a/142354Robert Harvey– Robert Harvey2017年06月15日 15:24:57 +00:00Commented Jun 15, 2017 at 15:24
-
@nvoigt , thanks for your comment. I have removed the concrete class that is injected. The reason I have used IOC is consistency.w0051977– w00519772017年06月15日 16:00:18 +00:00Commented Jun 15, 2017 at 16:00
1 Answer 1
I would inject ChangeDenominationFactory
only. The factory would then use a traditional new
construct to instantiate the immutable ChangeDenomination
object.
It is perfectly OK for this sort of pattern to co-exist with DI and Castle Windsor. Factories get a pass, as their single responsibility is construction of objects. If the factory itself has any dependencies, those should be injected into the factory, so that you can isolate and unit test.
A drawback here is that it's a little harder to unit test ChangeDenomination
, because you can't isolate away the constructor logic. That's probably OK, as long as the constructor doesn't depend on anything other than the constructor arguments. It sounds like that is the case, since you aren't injecting anything into it.
So my answer is
3) Don't register ChangeDenomination
with your IoC container at all.
If you want to be a purist and have a problem with this because you think it is "inconsistent," I am curious how you plan to use your IoC container to instantiate other immutable objects, such as string
:)
Explore related questions
See similar questions with these tags.