繁体   English   中英

Autofac-注册通用约束

[英]Autofac - Register generic constraint

我正在尝试向Autofac注册通用组件。 我遇到的问题与以下链接中的问题类似(错误消息相同)。 使用通用存储库将autofac与webapi绑定

我正在使用洋葱架构( http://jeffreypalermo.com/blog/the-onion-architecture-part-1/ )。 DbContext位于单独的层中,而业务层是将获取数据并执行与业务规则相关的各种操作的层。 上层只会知道接口IBaseDbManager。 我有一个垂直层,负责解决依赖关系。

下面的代码和Autofac配置示例如下:

商务课程:

public class BaseDbManager<TContext> : IBaseDbManager where TContext : DbContext, IBaseContext
{
    private readonly TContext _context;

    public BaseDbManager(TContext context)
    {
        _context = context;
    }

    public Partner GetPersonInfo(Expression<Func<Person,bool>> predicate)
    {
        var person = _context.Persons.Where(predicate).FirstOrDefault();
        return person;
    }
}

业务接口:

public interface IBaseDbManager
{
    Partner GetPersonInfo(Expression<Func<Person, bool>> predicate);
}

数据库上下文:

   [Database]
    public class BaseContext : DbContext, IBaseContext
    {
        public BaseContext()
            : base((string) ConnectionHelper.BaseConnectionString())
        {
            Database.SetInitializer<BaseContext>(null);
        }

        public virtual DbSet<Person> Persons { get; set; }
    }

上下文界面:

public interface IBaseContext
{
    DbSet<Partner> Partners { get; set; }
}

AUTOFAC模块:

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterType<BaseContext>().As<IBaseContext>().InstancePerLifetimeScope(); 
    builder.RegisterType(typeof(BaseDbManager<>)).As<IBaseDbManager>().InstancePerLifetimeScope();
}


问题在于,如果没有无参数构造函数,Autofac将不知道如何解析IBaseDbManager。 我需要由Autofac解决TContext。 您如何配置Autofac来解决这些情况? 我尝试注册为泛型并且基于构造函数,但它也不起作用。 如果我将new()添加到约束中并在无参数构造函数中创建实例,则它可以工作...我不想以这种方式解决它。

我想念什么?

问题在于,如果没有无参数构造函数,Autofac将不知道如何解析IBaseDbManager。

那不是问题。 这里的构造函数不是问题,Autofac不会对您的构造函数施加任何约束。

这里的问题是,在给定开放通用BaseDbManager<T> ,Autofac不知道要创建哪个封闭通用版本,因为给定的IBaseDbManager抽象是非通用的。 它无法为您推断通用类型。

有几种解决方案,但是由于应用程序中不同上下文类型的数量很可能非常有限(通常只有1个),因此在注册中指定此上下文类型最有意义。 例如:

builder.RegisterType(typeof(BaseDbManager<BaseContext>)).As<IBaseDbManager>()
    .InstancePerLifetimeScope();

如果BaseContext是您唯一的上下文类型,则使BaseDbManager<T>为非泛型甚至更有意义,因为只有当您实际计划更改类型参数T ,使它成为泛型才有意义。

我有两个与TContext约束匹配的对象(BaseContext和FakeBaseContext)。 BaseContext查询数据库,FakeBaseContext使用专门为单元测试创​​建的虚假数据。

这似乎不是拥有另一个上下文类的正当理由; 上下文是一组实体的定义; 在测试期间,您拥有相同的实体集。

在查看Autofac文档的几节内容后,我发现了与Steven的方法结合使用的注册件,该注册件使Autofact能够正确解决依赖关系(请参见下面的链接):

http://docs.autofac.org/en/latest/register/parameters.html?highlight=WithParameter

我最终编码的模块注册如下:

protected override void Load(ContainerBuilder builder)
{
    builder.RegisterType<BaseContext>()
           .As<IBaseContext>()
           .InstancePerLifetimeScope();

    builder.RegisterType<BaseDbManager<BaseContext>>().As<IBaseDbManager>()
           .WithParameter(new TypedParameter(typeof(BaseContext), new BaseContext()))
           .InstancePerLifetimeScope();
}

额外的反馈将不胜感激。 我将继续重构我的代码,因为我认为它可以改善。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM