So I'm well underway in my effort to convert my desktop/WPF solution from using Service Locator pattern to using Dependency Injection. So far it has been relatively painless (since the same UnityContainer is used in both cases): I just remove each call to my global/static ServiceLocator and put the dependency in the constructor. But I'm stumped when it comes to a helper service that exists in one of my entity classes.
Currently I have something like this: A singleton helper service which doesn't contain any state but just some commonly-used logic:
interface ICalculationsHelper { double DoCompletelyCrazyCalculations(); }
then, its use in an domain model entity:
class CrazyNumber
{
public int Id { get; set; }
public string Name { get; set; }
public double TheNumber { get; set; }
ICalculationsHelper _helper = ServiceLocator.Resolve<ICalculationsHelper>();
public CrazyNumber()
{
CreateCrazyNumber();
}
private void CreateCrazyNumber()
{
TheNumber = _helper.DoCompletelyCrazyCalculations();
}
}
...which is no problem for Entity Framework to materialize objects, and I can use this class in many ways (e.g. wrapping in ViewModels, manipulating in lists, etc) very simply because I'm just dealing with a default constructor.
Now what happens if I this (remove ServiceLocator and put the dependent helper in the constructor):
class CrazyNumber
{
public int Id { get; set; }
public string Name { get; set; }
public double TheNumber { get; set; }
ICalculationsHelper _helper;
public CrazyNumber(ICalculationsHelper helper)
{
_helper = helper;
CreateCrazyNumber();
}
private void CreateCrazyNumber()
{
TheNumber = _helper.DoCompletelyCrazyCalculations();
}
}
1) How is EF supposed to inject a new one of these helpers for each entity? 2) Say my app manipulates the entity in 100 places and in various different ways--all with a default constructor. Now all the sudden I have to modify each of those algorithms to manually pass an ICalculationsHelper into the entity. This is major clutter and complicates each algorithm. It seems much cleaner to have this "minor" service silently loaded in the background (as per service locator pattern). 3) If it turns out that using service locator is better in this case, how is this domain class supposed to be unit tested (mocking the service)?
Thanks