Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 声明程序集的作用域依赖项解析_C#_Plugins_Dependency Injection_Autofac - Fatal编程技术网

C# 声明程序集的作用域依赖项解析

C# 声明程序集的作用域依赖项解析,c#,plugins,dependency-injection,autofac,C#,Plugins,Dependency Injection,Autofac,早上好 短版本;实现我的常用定义的IMenuItem接口的所有程序集的所有具体实现都被注入到需要IEnumerable的所有构造函数中 我正在构建一个小的Windows TrayIcon应用程序核心,它允许插件。核心发现bin目录中的所有插件并创建我的Autofac容器 我有一个Core.Interfaces项目,它声明了一个IMenuItem接口 每个插件都是在自己的程序集中定义的,在这个插件中,可以有很多特性;每个功能都将声明其菜单项 在运行时,每个插件都会发现其菜单项的所有功能和查询。我遇

早上好

短版本;实现我的常用定义的IMenuItem接口的所有程序集的所有具体实现都被注入到需要
IEnumerable
的所有构造函数中

我正在构建一个小的Windows TrayIcon应用程序核心,它允许插件。核心发现bin目录中的所有插件并创建我的Autofac容器

我有一个
Core.Interfaces
项目,它声明了一个
IMenuItem
接口

每个插件都是在自己的程序集中定义的,在这个插件中,可以有很多特性;每个功能都将声明其菜单项

在运行时,每个插件都会发现其菜单项的所有功能和查询。我遇到的问题是,插件A从插件B接收菜单项,因为所有菜单项都实现了
IMenuItem
接口

我希望实现的是有一个通用的
IMenuItem
接口,但是当插件中的构造函数请求一个
IEnumerable
时,它应该只传递我们在它自己的程序集中发现的具体内容

我想说的是,如果我在每个程序集中声明IMenuItem接口,那么这一切都可以正常工作,大概是因为注册随后被命名为接口的名称空间


我正在努力寻找谷歌的正确术语,但我想我明白这是一个注册问题;也许我只能在解析时解决这个问题?

开箱即用,没有任何东西可以解决这个问题。您必须编写自定义代码

大部分自定义代码将取决于如何解析插件集。这里有几个选项可以解决这个问题,但是如果这两个选项都不适用于您当前的设计,也许您可以使用它们来激发您对其他想法的想象力

免责声明:我不是通过编译器运行所有这些。它们只是部分示例,我可能会打字。有些可能是伪代码。YMMV

选项1:在单独的生存期范围内注册每个插件

这就是为什么。基本上,根容器中只有共享组件,每个插件(以及相应的菜单项)都将注册到子范围中

var builder=newcontainerbuilder();
//注册所有插件都使用的常用内容
builder.Register().As();
var container=builder.Build();
//迭代程序集并为每个插件创建作用域
var pluginScopes=新列表();
foreach(GetThePluginAssemblies()中的var assembly)
{
var scope=container.BeginLifetimeScope(b=>
{
b、 RegisterAssemblyTypes(程序集)
.Where(t=>t.GetInterfaces().Any(i=>i==typeof(IPlugin))
.a实现接口();
b、 RegisterAssemblyTypes(程序集)
.Where(t=>t.GetInterfaces().Any(i=>i==typeof(IMenuItem))
.a实现接口();
});
pluginScopes.Add(范围);
}
此时,您有一个单独的作用域列表,可以用来解析每个插件,例如如果您需要所有插件:

var plugins=pluginScopes.SelectMany(s=>s.Resolve());
(我想这就是SelectMany的工作原理,我总是感到困惑。关键是你会得到一个所有范围内所有插件的扁平列表。)

为了让您的生活更轻松,从技术上讲,您可以使用
Autofac.multi租户
包并“假装”每个插件都是一个独立的租户。它已经构建了每个租户的所有范围跟踪和配置

var builder=newcontainerbuilder();
//注册所有插件都使用的常用内容
builder.Register().As();
var container=builder.Build();
//您可能不想“作为租户”从容器中解决问题,
//因此,您只需使用multi tenant.ApplicationContainer(用于全局/通用内容)
//或者单个租户直接作用域。从表面上看,租户ID策略不会
//所以只要做一个总是返回false或其他东西的伪函数。
var multipleUginContainer=新的多租户容器(容器,SomeTenantIdentificationStrategy);
//迭代程序集并为每个插件创建租户
//其中租户ID类似于程序集名称
foreach(GetThePluginAssemblies()中的var assembly)
{
MultipuginContainer.ConfigureTenant(assembly.FullName,b=>
{
b、 RegisterAssemblyTypes(程序集)
.Where(t=>t.GetInterfaces().Any(i=>i==typeof(IPlugin))
.a实现接口();
b、 RegisterAssemblyTypes(程序集)
.Where(t=>t.GetInterfaces().Any(i=>i==typeof(IMenuItem))
.a实现接口();
});
}
然后您可以获得插件列表(“租户”)并解析

var plugins=multipugincontainer
.GetTenants()
.SelectMany(k=>
multipugincontainer.gettenatScope(k.Resolve());
选项2:使用元数据标记项目

Autofac支持,
ResolvedParameter
功能非常强大。使用它进行一些巧妙的工作可以大有帮助

首先,您可以注册所有菜单项并用元数据标记它们

var builder=newcontainerbuilder();
//注册一堆东西然后。。。
foreach(GetThePluginAssemblies()中的var assembly)
{
builder.RegisterAssemblyTypes(程序集)
.Where(t=>t.GetInterfaces().Any(i=>i==typeof(IPlugin))
.a实现接口();
builder.RegisterAssemblyTypes(程序集)
.Where(t=>t.GetInterfaces().Any(i=>i==typeof(IMenuItem))
.WithMetadata(“assembly”,assembly.FullName)
.a实现接口();
}
好的,现在您已经将所有的
IMenuItem
条目标记为程序集名称。创建一个模块,自动将已解析的参数附加到每个
IPlugin
,这样任何
IEnumerable
都将由您的参数实现。这主要基于

公共类菜单模块:自动传真模块
{
ComponentPreparing(对象发送方,PreparingEventArg)上的私有静态无效