使用Constructor进行Autofac

问题描述 投票:1回答:3

我首先使用单元工作模式和entityFramework代码。现在我想使用Autofac来注册UnitOfWork,Repositories和My dbContext。

这是我的UnitOfWork代码:

public class UnitOfWork : IUnitOfWork
{
    private readonly DbContext _context;

    public UnitOfWork(DbContext context)
    {
        _context = context;

        Contact = new ContractRepository(context);
    }

    public void Dispose()
    {
        _context.Dispose();
        GC.SuppressFinalize(_context);
    }

    public IContactRepository Contact { get; private set; }

    public int Complete()
    {
        return _context.SaveChanges();
    }
}

这是我的存储库:

public class Repository<Entity> : IRepository<Entity> where Entity : class
{
    protected readonly DbContext _noteBookContext;
    public Repository(DbContext noteBookContext)
    {
        _noteBookContext = noteBookContext;
    }
    public void Add(Entity entity)
    {
        _noteBookContext.Set<Entity>().Add(entity);
    }
}

这是我的一个存储库:

public  class ContractRepository: Repository<Contact>,IContactRepository 
{
    public ContractRepository(DbContext noteBookContext) : base(noteBookContext)
    {

    }

    public DbContext NotebookContext
    {
        get
        {
            return _noteBookContext;
        }
    }
}

这是我的db上下文类:

public class NoteBookContext:DbContext
{
    public NoteBookContext(string connectionstring):base(connectionstring)
    {

    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ContactConfig());
        modelBuilder.Configurations.Add(new PhoneConfig());
        modelBuilder.Configurations.Add(new PhoneTypeConfig());
        modelBuilder.Configurations.Add(new GroupConfig());
        base.OnModelCreating(modelBuilder);
    }
    public DbSet<Contact> Contacts { get; set; }
    public DbSet<Phone> Phones { get; set; }

    public DbSet<Group> Groups { get; set; }

    public DbSet<PhoneType> PhoneTypes { get; set; }
}

现在我想用构造函数注册UnitOfWork(像这样的构造函数:)

var uow = new UnitOfWork(new NotebookdbContext("connectionstring"));

请注意,NoteBookContext是我的实体框架模型。

我写注册但我得到错误:

var builder = new ContainerBuilder();
builder.RegisterType<NoteBookContext>()
       .As<DbContext>();
builder.RegisterType<UnitOfWork>()
       .UsingConstructor(typeof(DbContext))
       .As<IUnitOfWork>();

builder.RegisterGeneric(typeof(Repository<>))
       .As(typeof(IRepository<>))
       .InstancePerLifetimeScope();

Container container = builder.Build();

这是我的错误:

Autofac.dll中出现未处理的“Autofac.Core.DependencyResolutionException”类型的异常附加信息:可以使用“DataLayer.NoteBookContext”类型的“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找到的构造函数都不可用服务和参数:

无法解析构造函数'Void .ctor(System.String)'的参数'System.String connectionstring'。

编辑2:

在Cyril Durand的回答帮助下,我写了以下注册配置:

 var builder = new ContainerBuilder();
        builder.RegisterType<ConnectionStringProvider>().As<IConnectionStringProvider>();
        builder.RegisterType<NoteBookContext>().As<DbContext>().WithParameter((pi, c) => pi.Name == "connectionstring",
                                                                              (pi, c) => c.Resolve<IConnectionStringProvider>().ConnectionString);
        builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().WithParameter(ResolvedParameter.ForNamed<DbContext>("connectionstring"));
        builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();

在我的代码中:

using (var scope = DependencyInjection.Container.BeginLifetimeScope())
        {
            var ConnectionString = scope.Resolve<IConnectionStringProvider>();
            ConnectionString.ConnectionString = "Context";

            var uw = scope.Resolve<IUnitOfWork>();
            var a =uw.Contact.GetAll();

        }

但我又得到了错误:

Autofac.dll中出现未处理的“Autofac.Core.DependencyResolutionException”类型异常

附加信息:在类型'NoteBookContext'上调用构造函数'Void .ctor(System.String)'时抛出异常。

大家能帮帮我吗?

entity-framework repository autofac unit-of-work
3个回答
3
投票

错误消息:

Autofac.dll中出现类型为Autofac.Core.DependencyResolutionException的未处理异常附加信息:使用Autofac.Core.Activators.Reflection.DefaultConstructorFinder类型的DataLayer.NoteBookContext找到的构造函数都不能使用可用的服务和参数调用:

无法解析构造函数System.String connectionstring的参数Void .ctor(System.String)

告诉您Autofac无法创建NoteBookContext,因为它无法解析connectionstring类型的名为String的参数。

你的NoteBookContext实现需要一个连接字符串,如果没有你告诉它,Autofac就无法知道它。注册NoteBookContext时,您必须指定connectionstring:

builder.RegisterType<NoteBookContext>()
       .As<DbContext>()
       .WithParameter("connectionstring", "XXX");

另一种具有动态分辨率和IConnectionStringProvider界面的解决方案:

public interface IConnectionStringProvider
{
    public String ConnectionString { get; }
}

和注册:

builder.RegisterType<ConnectionStringProvider>()
       .As<IConnectionStringProvider>()
       .InstancePerLifetimeScope(); 
builder.RegisterType<NoteBookContext>()
       .As<DbContext>()
       .WithParameter((pi, c) => pi.Name == "connectionstring", 
                      (pi, c) => c.Resolve<IConnectionStringProvider>().ConnectionString)
       .InstancePerLifetimeScope();

0
投票

没有看到错误就很难分辨。但你不需要使用UsingConstructor

//Make DbContext per request, if your app is web app (which has http request).
builder.RegisterType<NoteBookContext>()
       .As<DbContext>().WithParameter("connectionstring","ConnectionStringValue").InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();

builder.RegisterGeneric(typeof(Repository<>))
       .As(typeof(IRepository<>))
       .InstancePerLifetimeScope();

Container = builder.Build();

0
投票

您是否有理由将连接字符串传递给上下文?为您的unitofwork创建一个接口,并执行以下操作:

public class NoteBookContext:DbContext
{
    //Change connectionstring below with the name of your connection string in web.config
    public NoteBookContext():base("name=connectionstring")
    {

    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new ContactConfig());
        modelBuilder.Configurations.Add(new PhoneConfig());
        modelBuilder.Configurations.Add(new PhoneTypeConfig());
        modelBuilder.Configurations.Add(new GroupConfig());
        base.OnModelCreating(modelBuilder);
    }
    public DbSet<Contact> Contacts { get; set; }
    public DbSet<Phone> Phones { get; set; }

    public DbSet<Group> Groups { get; set; }

    public DbSet<PhoneType> PhoneTypes { get; set; }
}

并注册如下:

var builder = new ContainerBuilder();
builder.RegisterType<NoteBookContext>()
       .As<DbContext>()
       .InstancePerLifetimeScope();

builder.RegisterType<UnitOfWork>()
       .As<IUnitOfWork>()
       .InstancePerLifetimeScope();

builder.RegisterGeneric(typeof(Repository<>))
       .As(typeof(IRepository<>))
       .InstancePerLifetimeScope();

Container container = builder.Build();
© www.soinside.com 2019 - 2024. All rights reserved.