我意识到这个问题被问了很多。但是我想不出解决这个问题的方法。
我要解决的问题是创建三个独立的接口(interface)(Singleton Scoped、InstancePerRequest)。 并在其实现的接口(interface)下注册所有服务,而无需手动将它们添加到 DI 容器。
Autofac Scanning Assemblies for certain class type
Autofac register assembly types
Autofac assembly scanning - .NET Core
在你说重复之前听我说完。
I have provided a solution to the question asked. But i would like to search the whole solution and not be restricted to a project. I have addded my autofac module inside the Services project so it registers what exists inside services projects. Please see answer below for a better understanding.
I have tried to implement a multi project scanning see code below. It does not work.
这是我的 Program.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
这是我的启动类中的配置容器。我省略了所有其他项目,因为这只是一个新的 ASP.NET Core 项目。
public void ConfigureContainer(ContainerBuilder builder)
{
//builder.RegisterType<EpisodeServices>().As<IEpisodeService>().InstancePerLifetimeScope(); This works
var executingDirectory = AppDomain.CurrentDomain.BaseDirectory;
//The sth is my Solution's header for example Sth.Core, Sth.Models, Sth.Services all are childs to the Sth Solution
string[] files = Directory.GetFiles(executingDirectory, "Sth.*.dll", SearchOption.AllDirectories);
var listOfAssemblies = new List<Assembly>();
foreach (var file in files)
listOfAssemblies.Add(Assembly.LoadFile(file));
builder
.RegisterAssemblyTypes(listOfAssemblies.ToArray())
.Where(t => t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(ISthScopedService))))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
}
到目前为止一切顺利。
这是一个示例服务,因此您可以完整地看到我的实现。
public class EpisodeServices : IEpisodeService
{
public IList<Episode> GetEpisodes()
{
return new List<Episode>
{
new Episode { Id = 1, Name = "Some Name", Description = "Some Description" }
};
}
}
这是界面:
public interface IEpisodeService : ISthScopedService
{
IList<Episode> GetEpisodes();
}
这里是 Controller 的注入(inject)
public class EpisodeController : Controller
{
private readonly IEpisodeService _episodeService;
public EpisodeController(IEpisodeService episodeService)
{
_episodeService = episodeService;
}
public IActionResult Index()
{
var data = _episodeService.GetEpisodes();
return Content(data[0].Name);
}
}
如果我像这样运行它,我会得到一个无效操作异常:在尝试激活
。EpisodeController
时无法解析类型命名空间的服务。IEpisodeService
有人可以提供有关如何实现此目标的更多实现细节吗?
最佳答案
提供的解决方案不解决解决方案扫描。但它使用汇编扫描。您不妨将其视为有关如何实现这一目标的分步指南。我们的解决方案看起来像这样。
Sth.Core --> Class Library.
Sth.Services --> Class Library(Assembly scanning will happen here).
Sth.Web --> ASP.NET Core MVC project.
The Sth.Core has our three-lifetime interfaces which our Services need to inherit from.
- ISthInstanceService
- ISthScopedService
- ISthSingletonService
Sth.Web.Program.cs
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //Add this
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
Sth.Web,Startup.cs
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule(new SthModule()); // This is the autofac Module. We add it later at the Services Project
}
现在我们的服务项目。在这里我们需要创建我们的 autofac 模块。实例化的一个 asp.net 应用程序。
public class SthModule : Module
{
protected override void Load(ContainerBuilder builder)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
builder
.RegisterAssemblyTypes(assemblies)
.Where(t => t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(ISthScopedService))))
.AsImplementedInterfaces()
.InstancePerLifetimeScope(); // Add similar for the other two lifetimes
base.Load(builder);
}
}
上面的代码会扫描所有的Services项目,添加所有继承自ISthScopedService的类,并注册到容器中。
Sth.Service.EpisodeService.cs
public class EpisodeServices : IEpisodeService
{
public IList<Episode> GetEpisodes()
{
return new List<Episode>
{
new Episode { Id = 1, Name = "Imposter Syndrome", Description = "Imposter syndrome" }
};
}
}
还有界面。
public interface IEpisodeService : ISthCommonService
{
IList<Episode> GetEpisodes();
}
现在我们已经为我们的服务项目实现了程序集扫描(自动注册)。
关于c# - Autofac automate assembly scanning with Interfaces - .net core 3.0 - 根据Lifetime注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59164555/