如何将依赖项注入ELMAH自定义ErrorLog?

时间:2012-10-16 15:15:12

标签: c# ninject elmah

我有一个ELMAH自定义ErrorLog,它使用EF Code-First上下文来存储错误: -

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.

}

ErrorLog已连接到web.config: -

<errorLog type="MyProject.EntityFrameworkErrorLog, MyProject" />

我已经在项目的其他地方使用了Ninject。我想注入MyContext以便ErrorLog没有实例化它自己的依赖,但我没有运气在文档中找到钩子。 ELMAH似乎是在内部实例化ErrorLog,所以我似乎唯一的选择就是在我的自定义ServiceLocator中使用ErrorLog,如果可能的话,我希望避免使用{。}}。 p>

ELMAH中是否有更好的可用于注射的钩子?

1 个答案:

答案 0 :(得分:13)

ELMAH中的服务位置/倾向注入扩展点是ServiceCenter.Current属性,您可以在其中为委托提供以下签名:

public delegate IServiceProvider ServiceProviderQueryHandler(object context);

ELMAH将使用System.IServiceProvider返回的ServiceCenter.Current来解析ErrorLog次要问题。

所以你需要做3件事来用Ninject(或任何DI容器)来设置它

  1. 使用Ninject创建您自己的System.IServiceProvider实现,IKernel接口已经来自System.IServiceProvider,所以已经完成。
  2. 您需要在容器中注册EntityFrameworkElmahErrorLog作为ErrorLog实施,因为ELMAH会尝试解析ErrorLog的实例。
  3. 将您的代表提供给ServiceCenter.Current
  4. 因此,您需要RegisterServices方法中的以下内容:

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<ErrorLog>().To<EntityFrameworkElmahErrorLog>();
        ServiceCenter.Current = (httpContext) => kernel;
    }  
    

    注意:在ServiceProviderQueryHandler代表中,您可以获得当前HttpContext,然后您就可以微调您的权宜之计。

    您还应注意,使用此方法,您将无法在配置文件中配置ErrorLog

    ELMAH将始终使用容器中已解析的实例,因为内置的ServiceContainer会读取您使用自定义逻辑覆盖的配置文件。