我知道这个问题被问得很多。但我无法找出解决这个问题的方法,我试图解决的是创建三个独立的接口(Singleton Scoped,InstancePerRequest)。
我试图解决的是创建三个独立的接口(Singleton Scoped,InstancePerRequest).并在其实现的接口下注册所有的服务,而不必手动将它们添加到DI容器中。
在你说重复之前,听我说完。
我已经提供了一个所问问题的解决方案。但我想搜索整个解决方案,而不是局限于一个项目。我已经在服务项目中添加了我的autofac模块,所以它可以注册服务项目中存在的东西。请看 回答 下图,以便更好的理解。
我曾试着实现多项目扫描见下面的代码。它不工作。
这是我的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>();
});
}
这是我的Startup类中的Configure容器。由于这只是一个新的ASP.NET核心项目,所以我省略了所有其他的内容。
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();
}
这是控制器的注入
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);
}
}
如果我像这样运行这个,我得到的是 Invalid Operation Exception: Unable to resolve service for type namespace.IEpisodeService
试图启动 EpisodeController
.
谁能提供更多的实现细节,说明如何实现?
提供的解决方案并不能解决解决方案扫描的问题。但是回答了这个问题。
现在你看到有一个解决方案的工作原理和上面的代码非常相似。
但是有一个限制条件。你的接口需要和你的构建器和基础实现在同一个项目中。
你可以把它看成是如何实现这个目标的一步步指南。
我们的解决方案看起来是这样的。
三个解决方案项目
Sth.Core --> 类库。
Sth.Services --> Class Library.Sth.Web --> ASP.NET Core MVC项目。
Sth.Web --> ASP.NET Core MVC项目。
Sth.Core有我们的三生接口,我们的Services需要继承它。
Sth.Core
这三个都是空接口。
Sth.Web我们需要在这里编辑2个文件,程序.cs,启动.cs。
程序.cs和启动.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>();
});
}
程序.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 app里面实例化。
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);
}
}
上面的代码将sacn所有的Services项目,并添加所有继承自ISthScopedService的类,并将它们注册到容器中。
下面是我们在Service项目里面的ServiceInstances。
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();
}
现在我们已经为我们的服务项目实现了汇编扫描(自动注册)。