I am running an MVC app that contains a number of services (that call other services/helpers/etc). I am trying to inject parameter values that are only known at runtime using the strategy outlined
As mentioned in the article it is preferable to not simply use Unity as a ServiceLocator - as well, I would much prefer not to new-up an instance of the UnityContainer (and write a fairly ugly Resolve statement) every time I want to do anything out of the ordinary (like inject runtime parameters).
The article is now a couple of years old and Unity now supports TypeFactory and DelegateFactory types, so it could easily be improved but the idea of injecting a delegate into the constructor to go and get your parameter values nicely decouples the process (note I'm happy to discuss equally decoupled strategies such as abstracting to a factory)
I'm almost there with the delegate approach described in the article however although I can inject the delegate and get the delegate to call out to get the values in an abstracted class, the instance of that class is different to the one where I place the values, hence the values the delegate call sees are null
I've tried using named registrations, and tried different lifetime options to no avail - typically it makes little difference or Unity doesn't pickup the resolution and I get the ...make sure there is parameterless constructor... exception message. Also note that if I am off the mark with how the parameters are assigned and retrieved, feel free to comment
The essence of my code is as follows
Bootstrap:
container.RegisterType<IExportDetail, ExportDetail>();
container.RegisterType<IExportHelper, ExportHelper>();
container.RegisterType<Func<IExportDetail>>(
new InjectionFactory(c =>
//new Func<string, IExportDetail>(name => c.Resolve<IExportDetail>(name))));
new Func<IExportDetail>(() => container.Resolve<IExportDetail>())));
Abstracted parameter declarations:
public interface IExportDetail
{
string Parm1{ get; set; }
string Parm2{ get; set; }
}
public class ExportDetail : IExportDetail
{
public string Parm1{ get; set; }
public string Parm2{ get; set; }
}
Helper/Service being called:
public class ExportHelper : IExportHelper
{
private IExportDetail _service;
public ExportHelper(
Func<IExportDetail> serviceFactory
)
{
_service = serviceFactory();
_parm1 = _service.Parm1; // <--!!this is null!!
_parm2 = _service.Parm2; // <--!!this is null!!
}
}
Caller :
IExportHelper _exportHelper; //<--DI'd
IExportDetail _exportDetail; //<--DI'd
_exportDetail.Parm1 = parm1ValueSetAtRuntime;
_exportDetail.Parm2 = parm2ValueSetAtRuntime;
return _exportHelper;
ExportDetail, which would not need an interface). See this article to understand the difference between newables (which you should just use the new keyword for) and injectables. - NightOwl888