5

我有一个使用 EF Code-First 上下文来存储错误的 ELMAH 自定义错误日志:-

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在我的 custom 内部使用ErrorLog,如果可能的话我想避免。

ELMAH 中是否有更好的钩子可供我用来注入?

4

1 回答 1

13

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

public delegate IServiceProvider ServiceProviderQueryHandler(object context);

ELMAH 将使用System.IServiceProvider返回的ServiceCenter.Current解决ErrorLog实例。

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

  1. System.IServiceProvider使用 Ninject创建您自己的实现,IKernel接口已经从 from 派生System.IServiceProvider,所以它完成了。
  2. 您需要EntityFrameworkElmahErrorLog在您的容器中注册您作为ErrorLog实现,因为 ELMAH 将尝试解析ErrorLog.
  3. 将您的代表提供给ServiceCenter.Current

因此,您的方法中需要类似以下内容RegisterServices

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

注意:在ServiceProviderQueryHandler委托中,您可以获得当前HttpContext的,并且您可以微调您的权宜之计是如何解决的。

您还应该注意,使用这种方法,您将无法ErrorLog在配置文件中进行配置。

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

于 2012-10-19T11:18:59.877 回答