簡體   English   中英

使用Autofac的.NET Core(MYSQL)通用存儲庫自動裝配

[英].NET Core (MYSQL) Generic Repository AutoWiring using Autofac

我的目標是實現以下目標。 我正在嘗試使用以下方法設置新的解決方案:MySQL,.NET Core,Autofac,EF Core ...利用(通用)存儲庫模式。

最終,我將跳到具有現有數據庫的項目,因此我的目標是以某種方式利用(t4)模板和EF生成一些模型,然后“應該”(著名的最后一句話)像為需要與之交互的每個模型制作一個回購協議。 (每個回購將只是一個小的輕量級類繼承基)

啟動文件

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        this.Configuration = builder.Build();
    }

    public IConfigurationRoot Configuration { get; private set; }

    // This method gets called by the runtime. 
    // Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.
            .AddDbContext<MyContext>(o => o.UseMySQL(
          Configuration.GetConnectionString("MyConnection")));
    }

    public void ConfigureContainer(ContainerBuilder builder)
    {               
        builder.RegisterGeneric(typeof(Repository<>))
            .As(typeof(IRepository<>))
            .InstancePerLifetimeScope();

       // the below works (before adding the repos)
       builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
           .AssignableTo<IService>()
           .AsImplementedInterfaces()
           .InstancePerLifetimeScope();
    }
}

(通用)Repository.cs

public abstract class Repository<T> : IRepository<T>
    where T : class
{
    private readonly MyContext _context;

    protected Repository(MyContext context)
    {
        _context = context;
    }

    public virtual string Add(T entity)
    {
        if (ValidateAdd(ref entity, out var message))
        {
            _context.Set<T>().Add(entity);
        }

        return message;
    }

    public virtual bool ValidateAdd(ref T entity, out string message)
    {
        message = default(string); 
        return true;
    }

}

如果存儲庫,則實現:

FooRepository.cs

// public interface IFooRepository: IRepository<Foo>

public class FooRepository: Repository<Foo>, IFooRepository
{
    public FooRepository(MyContext context) : base(context)
    {
    }

    public override bool ValidateAdd(ref Foo entity, out string message)
    {
        // just a hook for pre-insert stuff
        message = "All foos shall fail add";
        return false;
    }
}

然后是服務或控制器中的用法,或者您擁有什么。

FooService.cs

public class FooService: IFooService
{
    private readonly IFooRepository _repository;

    public FooService(IFooRepository repository)
    {
        _repository = repository;
    }

    public void DoSomethingThenAdd()
    {
       // some other business logic specific to this service
        _repository.Add(new Foo()
        {
            Id = 1,
            LastName = "Bar",
            Name = "Foo"
        });
    }
}

問題:

我該如何進行所有這些連接...我一直在努力尋找有關MySQL + Ef的適當文檔,而且我有點直覺認為那部分是“有效的”。 但是,正如您在下面的錯誤日志中看到的那樣,我對存儲庫的注冊搞砸了。

錯誤:

激活特定注冊期間發生錯誤。

有關詳細信息,請參見內部異常。

注冊:激活程序= FooService(ReflectionActivator),服務= [MyApp.Services.Interfaces.IFooService,MyApp.Services.Interfaces.IService],生命周期= Autofac.Core.Lifetime.CurrentScopeLifetime,共享=共享,所有權= OwnedByLifetimeScope

--->使用可用服務和參數調用類型為“ MyApp.Services.FooService”的“ Autofac.Core.Activators.Reflection.DefaultConstructorFinder”找不到的構造函數:

無法解析構造函數'Void .ctor(MyApp.Data.Interfaces.IFooRepository)'的參數'MyApp.Data.Interfaces.IFooRepository存儲庫'。 (有關詳細信息,請參見內部異常。)

-> Autofac.Core.DependencyResolutionException:在類型為“ MyApp.Services.FooService”的“ Autofac.Core.Activators.Reflection.DefaultConstructorFinder”中找不到任何構造函數,都不能使用可用的服務和參數進行調用:

無法解析構造函數'Void .ctor(MyApp.Data.Interfaces.IFooRepository)'的參數'MyApp.Data.Interfaces.IFooRepository存儲庫'。

以下行將在Autofac中將Repository<Foo>注冊為IRepository<Foo>

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

但是IRepository<Foo>不是IFooRepository並且FooService需要IFooRepository 這就是為什么Autofac失敗並顯示以下錯誤消息:

無法解析構造函數'Void .ctor(MyApp.Data.Interfaces.IFooRepository)'的參數'MyApp.Data.Interfaces.IFooRepository存儲庫'。

如果要保留FooRepositoryIFooRepository ,則必須注冊它們:

builder.RegisterType<FooRepository>()
       .As<IFooRepository>()

另一個解決方案是注冊IRepository<>所有實現

builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
       .AsClosedTypesOf(typeof(IRepository<>))

FooService應該依賴Irepository<Foo>而不是IFooRepository

public class FooService: IFooService
{
    private readonly IRepository<Foo> _repository;

    public FooService(IRepository<Foo> repository)
    {
        this._repository = repository;
    }

    // ...
}

順便說一句,使用IIS時要小心進行程序集掃描: 程序集掃描-IIS托管應用程序

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM