2016-04-25 73 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();