2016-04-25 102 views
0

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

这是我的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; 
     } 
    } 
} 

,这是我的分贝上下文类别:

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(); 

这是我的错误:

An unhandled exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll Additional information: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'DataLayer.NoteBookContext' can be invoked with the available services and parameters:

Cannot resolve parameter 'System.String connectionstring' of constructor 'Void .ctor(System.String)'.

编辑2:

从西里尔·杜兰德的回答后帮我写下列注册配置:

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(); 

     } 

,但我得到的错误再次:

An unhandled exception of type 'Autofac.Core.DependencyResolutionException' occurred in Autofac.dll

Additional information: An exception was thrown while invoking the constructor 'Void .ctor(System.String)' on type 'NoteBookContext'.

每个人都可以帮我吗?

+1

您可以编辑您的文章,包括错误消息? –

+0

@CyrilDurand:我包含错误 –

回答

2

错误消息:

An unhandled exception of type Autofac.Core.DependencyResolutionException occurred in Autofac.dll Additional information: None of the constructors found with Autofac.Core.Activators.Reflection.DefaultConstructorFinder on type DataLayer.NoteBookContext can be invoked with the available services and parameters:

Cannot resolve parameter System.String connectionstring of constructor Void .ctor(System.String) .

告诉你Autofac不能创建一个NoteBookContext,因为它可以解决一个名为String类型的connectionstring参数。

您的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

如何在解析时间中添加参数和设置值? –

+0

@minamorsali看到我的编辑 –

+0

非常感谢您的答案。实际上我希望结束程序员在解析时传递参数值。可能吗? –

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

我测试你的代码,而不是我的,这个原因如下错误:在Autofac.dll中发生未经处理的类型'Autofac.Core.DependencyResolutionException'的异常,附加信息:没有找到'Autofac .Core.Activators.Reflection.DefaultConstructorFinder'类型'BussinessLayer.Repositories.UnitOfWork'可以用可用的服务和参数调用: –

+0

您在UnitOfWork上有多少构造函数? –

+0

只有一个构造函数 –

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(); 
相关问题