in a webforms application, let's say we have a class that has a method that does some job with the use of DateTime.Now, if I want to test this method I can inject a DateTimeWrapper using the constructor but in my scenario I don't want the IoC container to construct the class for me, instead I want to use it "new it" and have it testable and I think it makes no sense that each time we want to use this class, a dependency of the DateTimeWrapper "which returns the real DateTime.Now" should be injected!
Note: nothing is being injected in the WebForms page class.
public class EmailNotification
{
public IDateTimeWrapper DateTimeWrapper { get; set; }
public void SetBody(string body)
{
...
Body = body + DateTimeWrapper.Now.ToString();
}
}
I tried to use Property injection using "Autofac" and the following works perfect:
builder.RegisterType<DateTimeWrapper>()
.As<IDateTimeWrapper>();
builder.RegisterType<EmailNotification>().PropertiesAutowired();
// in this case, it works
var email = container.Resolve<EmailNotification>();
email.SetBody("hello world!");
But I need to use the component like this:
// somehow I want the DateTimeProvider "the real one" to be injected or used at this point
var email= new EmailNotification();
email.SetBody("hello world!");
// I'm getting a NullReferenceException at the last line because the dependency has been never injected
do you have an idea? thanks in advance
the solution was simple "i think", I changed this:
public class EmailNotification
{
public IDateTimeWrapper DateTimeWrapper { get; set; }
public void SetBody(string body)
{
...
Body = body + DateTimeWrapper.Now.ToString();
}
}
to the following:
public class EmailNotification
{
private IDateTimeWrapper _dateTimeWrapper = new DateTimeWrapper();
public IDateTimeWrapper DateTimeWrapper
{
get
{
return _dateTimeWrapper;
}
set
{
_dateTimeWrapper = value ?? throw new ArgumentNullException(nameof(DateTimeWrapper));
}
}
public void SetBody(string body)
{
...
Body = body + DateTimeWrapper.Now.ToString();
}
}
so I still have IDateTimeWrapper as a seam for unit testing and at the same time it gets initialized by default when constructing an instance of the EmailNotification class.