【问题标题】:Dependency Injection for EF with Autofac on Web API在 Web API 上使用 Autofac 对 EF 进行依赖注入
【发布时间】:2014-07-29 15:20:21
【问题描述】:

在我的 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 请求?

【问题讨论】:

    标签: entity-framework asp.net-web-api dependency-injection autofac


    【解决方案1】:

    防止在 DbContext 中使用 service locator anti-pattern。 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();    
    

    【讨论】:

    • @Tim:是的,DbContext 是工作单元模式的实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 2018-12-31
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 2014-09-30
    • 2017-10-22
    相关资源
    最近更新 更多