I have an ELMAH custom ErrorLog that uses an EF Code-First context to store the errors:-
class EntityFrameworkElmahErrorLog
{
public EntityFrameworkElmahErrorLog(IDictionary config) : this() { }
public override ErrorLogEntry GetError(string id)
{
using (var context = new MyContext())
{
var intId = Int64.Parse(id, CultureInfo.InvariantCulture);
var item = context.ErrorLog.Single(x => x.Id == intId);
return new ErrorLogEntry(this, id, ErrorXml.DecodeString(item.Details));
}
}
// etc.
}
The ErrorLog is wired up in the web.config:-
<errorLog type="MyProject.EntityFrameworkErrorLog, MyProject" />
I’m already using Ninject elsewhere in the project. I’d like to inject MyContext so that the ErrorLog isn’t instantiating its own dependency, but I’m not having any luck finding a hook in the documentation. ELMAH appears to be instantiating the ErrorLog internally, so the only option I seem to have is using a ServiceLocator inside my custom ErrorLog, which I’d like to avoid if possible.
Are there any better hooks available in ELMAH that I can use to inject ?
The Service location/Depdency injection extension point in ELMAH is the
ServiceCenter.Currentproperty where you can provide a delegate with the following signature:ELMAH will use the
System.IServiceProviderreturned by theServiceCenter.Currentto resolve theErrorLogisntances.So you need to do 3 things to setup it with Ninject (or any DI container)
System.IServiceProviderimplementation with Ninject theIKernelinterface already derives from fromSystem.IServiceProvider, so it’s done.EntityFrameworkElmahErrorLogin your container as anErrorLogimplemenation, because ELMAH will try to resolve an instance ofErrorLog.ServiceCenter.CurrentSo you need something like the following in your
RegisterServicesmethod:Note: in in the
ServiceProviderQueryHandlerdelegate you get the currentHttpContextand with that you can fine tune how your expediencies are resolved.You should also note that with this approach you will lose the ability to configure your
ErrorLogin your config file.ELMAH will always use the resolved instance from your container, because the built in
ServiceContainerreads the config file what you override with your custom logic.