Today, I had a problem of how to construct an object passing a specific date into the constructor. Normally, this is not an issue encountered frequently as only “services” are passed via constructor injection. This time however, I needed to make sure a date was passed when the object was created, and this date needs to be evaluated each time.
I’m not a fan of the “initialise” pattern, so that was out. Here is how I solved the problem using Unity DI Container.
First, I defined a dependency and an implementation:
public interface IService { void DoSomething(); } public class Service : IService { private readonly DateTime date; public Service(DateTime date) { this.date = date; } public void DoSomething() { Console.WriteLine(date); } }
Then, configure the container, and attempt to make some calls:
IUnityContainer container = new UnityContainer(); container.RegisterType<IService, Service>( new InjectionConstructor( new InjectionParameter<DateTime>(DateTime.Now) )); var dateService = container.Resolve<IService>(); // prints datetime container was configured dateService.DoSomething(); Console.Read(); // still datetime container was configured dateService.DoSomething();
Ok, so this is not doing what I wanted. The DateTime is being captured. This is not surprising, as the value is copied into the constructor.
If we resolve the item from the container again, we still get the same value:
dateService = container.Resolve<IService>(); // still datetime container was configured with dateService.DoSomething();
This was annoying, it seems we need some sort of factory or delegate that is resolved each time the object is constructed:
public interface IDateFetchingFactory { DateTime GetDate(); } public class DateFetchingFactory : IDateFetchingFactory { public DateTime GetDate() { return DateTime.Now; } } public class Service2 : IService { private readonly IDateFetchingFactory dateFetchingFactory; public Service2(IDateFetchingFactory dateFetchingFactory) { this.dateFetchingFactory = dateFetchingFactory; } public void DoSomething() { Console.WriteLine(dateFetchingFactory.GetDate()); } }
Now we can register our new type:
container.RegisterType<IService, Service2>("Service2"); container.RegisterType<IDateFetchingFactory, DateFetchingFactory>();
and each time we make a call, we get the behaviour we wanted:
dateService.DoSomething(); // datetime when method call was made via factory Console.Read(); dateService.DoSomething(); // a different datetime from factory
There must be other ways of achieving this, is there a better way?