Autofac会覆盖通用类型的上次注册

时间:2017-10-09 10:58:01

标签: c# generics dependency-injection autofac

我正在尝试使用Autofac注册泛型类型,但最后一个值最终会覆盖先前的值。公共项目具有实体服务接口

public interface IEntityService<TEntity> where TEntity : class
{
    TEntity GetByID(object id);
}

实施类,项目A

public class EntityService<TEntity> : Common.IEntityService<TEntity> where TEntity : class
{
    protected IContext _iContext;
    protected DbSet<TEntity> _iDbSet;

    public EntityService(IContext context)
    {
        _iContext = context;
        _iDbSet = IContext.Set<TEntity>();
    }

    public virtual TEntity GetByID(object id)
    {
        return IDbSet.Find(id);
    }
}

实施班级项目B

public class EntityService<TEntity> : Common.IEntityService<TEntity> where TEntity : class
{
    protected ILogDbContext  _iLogDbContext;
    protected DbSet<TEntity> _iDbSet;

    public EntityService(ILogDbContext context)
    {
        _iLogDbContext = context;
        _iDbSet = IContext.Set<TEntity>();
    }

    public virtual TEntity GetByID(object id)
    {
        return _iDbSet.Find(id);
    }
}

在web.api中注册

var builder = new ContainerBuilder();
builder.RegisterModule(new EFModule());
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

EFModule类

public class EFModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
      builder.RegisterGeneric(typeof(Service.EntityService<>))
      .As(typeof(Common.IEntityService<>))
      .Named(Common.ConfigType.ProjectType.Main,typeof(Common.IEntityService<>))
      .InstancePerDependency();

      builder.RegisterGeneric(typeof(LogProject.Service.EntityService<>))
      .As(typeof(Common.IEntityService<>))
      .Named(Common.ConfigType.ProjectType.Log, typeof(Common.IEntityService<>))
      .InstancePerDependency();
   }
}

正在发生的事情是,对于最后的任何配置,一切正常。说,我把

builder.RegisterGeneric(typeof(LogProject.Service.EntityService<>))

在web.config中,项目类型为LogProject。然后它工作正常,但如果我把MainProject放在配置文件中。相反的情况正好相反,无论最后一行(MainLog),module中的哪一行,如果在web.config中它不相同,它会覆盖抛出一个例外。基本上,泛型不是基于但是会被解析,而是被最后一个值所覆盖。

1 个答案:

答案 0 :(得分:1)

您正在注册CASE WHEN [Current Description]='Testing' THEN 'Invited to Test' WHEN [Current Description]<>'Rejected' AND 'Testing' IN ([Student History Description] FOR [Test Code]) THEN 'Invited to Test' ELSE '' END 的2个实例。上次注册的实例获胜是正常和预期的行为。

the documentation

  

如果多个组件公开同一服务, Autofac将使用上次注册的组件作为该服务的默认提供商

如果您希望Autofac能够区分两者,您可以选择以下几种方法:

创建单独的抽象

typeof(Common.IEntityService<>)

将上述界面用于Log项目的构造函数参数,并将其注册为:

public interface ILogEntityService<TEntity> : IEntityService<TEntity> where TEntity : class
{
}

使用具体类型/ AsSelf

builder.RegisterGeneric(typeof(Service.EntityService<>))
  .As(typeof(Common.IEntityService<>))
  .Named(Common.ConfigType.ProjectType.Main,typeof(Common.IEntityService<>))
  .InstancePerDependency();

builder.RegisterGeneric(typeof(LogProject.Service.EntityService<>))
  .As(typeof(ILogEntityService<>))
  .Named(Common.ConfigType.ProjectType.Log, typeof(Common.IEntityService<>))
  .InstancePerDependency();

然后在服务构造函数中使用具体类型

builder.RegisterGeneric(typeof(Service.EntityService<>))
  .AsSelf()
  .Named(Common.ConfigType.ProjectType.Main,typeof(Common.IEntityService<>))
  .InstancePerDependency();

builder.RegisterGeneric(typeof(LogProject.Service.EntityService<>))
  .AsSelf()
  .Named(Common.ConfigType.ProjectType.Log, typeof(Common.IEntityService<>))
  .InstancePerDependency();

当然,在能够交换/模拟实现方面,使用第一个选项会更好。