C# Autofac:是否将打开的泛型类型注册为非泛型抽象父类型的实例?

C# Autofac:是否将打开的泛型类型注册为非泛型抽象父类型的实例?,c#,generics,inversion-of-control,autofac,C#,Generics,Inversion Of Control,Autofac,我用一个动态灵活的插件系统来维护遗留代码,该系统被实现为一个非常浅的类树,其中所有具体的插件都扩展了抽象的plugin类。大多数插件都是具体的类(如LoadSound,HighPassFilter),但其中一些插件只有一个泛型类型参数(如CreateCopy) 该系统的初始化序列基本上加载所有程序集,列出其所有类型,选择插件的后代,然后对其进行迭代,并将其插入某种自制IoC容器中 为了提高这个系统的可维护性,我想用代码库中其他地方使用的Autofac替换自制IoC容器 我以一种有用的方式注册了所

我用一个动态灵活的插件系统来维护遗留代码,该系统被实现为一个非常浅的类树,其中所有具体的插件都扩展了抽象的
plugin
类。大多数插件都是具体的类(如
LoadSound
HighPassFilter
),但其中一些插件只有一个泛型类型参数(如
CreateCopy

该系统的初始化序列基本上加载所有程序集,列出其所有类型,选择
插件
的后代,然后对其进行迭代,并将其插入某种自制IoC容器中

为了提高这个系统的可维护性,我想用代码库中其他地方使用的Autofac替换自制IoC容器

我以一种有用的方式注册了所有类型,如下所示:

Autofac.ContainerBuilder生成器;
//找到从插件派生的所有类,并拆分它们
//根据它们是否通用而确定
ILookup isGeneric=类型。其中(IsPlugin)
.ToLookup(t=>t.IsGenericTypeDefinition);
//将泛型类型注册为它们自己
foreach(在isGeneric[true]中键入t)
建造商注册通用(t)
.AsSelf()
.SingleInstance();
//将所有非泛型类型注册为它们自己和
//作为插件的实例
builder.RegisterTypes(isGeneric[false].ToArray())
.AsSelf()
.As()
.SingleInstance();
有了它,我可以成功地从以后从
builder
创建的容器中解析任何插件。问题是系统还需要一个
GetAvailablePlugins
方法。我的第一反应是把这当作一个计划来实施

public-IReadOnlyCollection-GetAvailablePlugins()
{
返回组件。解析()
.Select(plugin=>newpluginmetadata(plugin.GetType()))
.ToList();
}
(我知道从IoC容器手动解析是一个坏主意,但解决这一问题是下一步,而不是我现在遇到的问题。)

然而,正如您可能已经猜到的,这只会导致非通用插件的集合,而不是通用插件的集合。我天真地尝试将泛型类型注册到

builder.RegisterGeneric(t)
.AsSelf()
.As()
.SingleInstance();
但Autofac不想要这些:

The service 'Vendor.Common.Plugin' is not an open generic type definition.
当然,这是一个准确的观察。事实并非如此。我也不希望
Plugin
的解析尝试会导致通用插件的具体实例——我只希望有一个好方法,可以访问注册为
Plugin
s的所有类型,而不必在其他地方复制该信息


有什么想法吗?

写下问题后没过多少分钟,我就想出了办法:我把注册逻辑改为

//查找从插件派生的所有类
IEnumerable plugins=types.Where(IsPlugin);
//将所有插件(通用和非通用)注册为插件的子插件
builder.RegisterTypes(plugins.ToArray())
.AsSelf().As().SingleInstance();
//以可解析的方式注册通用插件
foreach(在modules.Where中键入t(t=>t.IsGenericTypeDefinition))
builder.RegisterGeneric(t.AsSelf().SingleInstance();
我不太清楚这是如何工作的,但它似乎注册了通用插件,就好像它们是非通用组件一样。这些非通用组件无法在系统中解析,但在向Autofac询问实现
插件
服务的所有组件时,会返回它们

除此之外,我还将泛型插件注册为泛型组件,这样系统就可以用具体的类型参数来解析它们


更新:然而,我现在发现

Components.Resolve()
.Select(plugin=>newpluginmetadata(plugin.GetType()))
.ToList();
不是一个可行的路径–当运行验证此插件列表的某些属性的测试时,某些插件的依赖项无法实例化。因此,我决定将我的答案与下面的答案结合起来:

我现在用

Components.ComponentRegistry
.Registrationfor(新类型服务(类型化(基本模块)))
.Select(reg=>newpluginmetadata(reg.Activator.LimitType))
.ToList();

写下问题后没过多少分钟,我就明白了该怎么做:我将注册逻辑更改为

//查找从插件派生的所有类
IEnumerable plugins=types.Where(IsPlugin);
//将所有插件(通用和非通用)注册为插件的子插件
builder.RegisterTypes(plugins.ToArray())
.AsSelf().As().SingleInstance();
//以可解析的方式注册通用插件
foreach(在modules.Where中键入t(t=>t.IsGenericTypeDefinition))
builder.RegisterGeneric(t.AsSelf().SingleInstance();
我不太清楚这是如何工作的,但它似乎注册了通用插件,就好像它们是非通用组件一样。这些非通用组件无法在系统中解析,但在向Autofac询问实现
插件
服务的所有组件时,会返回它们

除此之外,我还将泛型插件注册为泛型组件,这样系统就可以用具体的类型参数来解析它们


更新:然而,我现在发现

Components.Resolve()
.Select(plugin=>newpluginmetadata(plugin.GetType()))
.ToList();
不是一个可行的路径–当运行验证此插件列表的某些属性的测试时,某些插件的依赖项无法实例化。因此,我决定将我的答案与下面的答案结合起来:

我现在用

Co