在Web API上使用Autofac进行EF的依赖注入



我在DbContext中保存实体时动态注入了一个内务管理服务。

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
    var t = entityEntry.Entity.GetType();
    // Housekeep
    var castEntityEntry = castDbEntityEntryMethod
        .MakeGenericMethod(new[] { t })
        .Invoke(entityEntry, null);
    housekeepEntityMethod
        .MakeGenericMethod(new[] { t })
        .Invoke(this, new[] { castEntityEntry });
    return base.ValidateEntity(entityEntry, items);
}
private void HousekeepEntity<TEntity>(DbEntityEntry<TEntity> entity)
    where TEntity : class
{
    var housekeeper = DbConfiguration.DependencyResolver.GetService<IHousekeeper<TEntity>>();
    if (housekeeper != null)
    {
        housekeeper.Maintain(entity);
    }
}

我一直在传递IComponentContext到处,所以我可以解决那里的类型,但与EF6我希望使用依赖注入:

private class AutofacDbDependencyResolver : AutofacWebApiDependencyResolver, IDbDependencyResolver
{
    public AutofacDbDependencyResolver(ILifetimeScope container)
        : base(container)
    {
    }
    public object GetService(System.Type type, object key)
    {
        using (var scope = this.GetRequestLifetimeScope())
        {
            if (scope == null)
            {
                return null;
            }
            object service;
            scope.TryResolve(type, out service);
            return service;
        }
    }
    public System.Collections.Generic.IEnumerable<object> GetServices(System.Type type, object key)
    {
        using (var scope = this.GetRequestLifetimeScope())
        {
            if (scope == null)
            {
                return System.Linq.Enumerable.Empty<object>();
            }
            object service;
            if (scope.TryResolve(type, out service))
            {
                return new object[] { service };
            }
            else
            {
                return System.Linq.Enumerable.Empty<object>();
            }
        }
    }
}

设置容器时:

System.Data.Entity.DbConfiguration.Loaded += (s, e) =>
    e.AddDependencyResolver(new AutofacDbDependencyResolver(container), overrideConfigFile: false);

但是我的生命周期作用域返回null。我如何获得调用此操作的当前API请求?

防止在DbContext中使用服务定位器反模式。EF6现在允许您解决这个问题并不重要,它仍然是一个反模式。相反,只需使用依赖注入或允许通过挂接事件来添加此内务管理。例如,您可以为您的实体编写一个部分类:

public partial class MyEntities
{
    public event Action<DbContext> SavingChanges = _ => { };
    public override int SaveChanges()
    {
        this.SavingChanges(this);
        return base.SaveChanges();
    }
}

这样,你可以简单地挂钩到SavingChanges事件,当有人调用SaveChanges时,该事件将被引发:

builder.Register<MyEntities>(context =>
{
    var db = new MyEntities();
    db.SavingChanges += context.Resolve<IHouseKeepingService>().HousekeepEntities;
    return db;
}).InstancePerLifetimeScope();    

最新更新