[英]Registering dynamic generic repository with Autofac ASP.Net Core 5
[英].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存儲庫'。
如果要保留FooRepository
和IFooRepository
,則必須注冊它們:
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.