C# 使用Autofac查找插件

C# 使用Autofac查找插件,c#,autofac,C#,Autofac,花了很长时间弄清楚如何让Autofac加载插件。我是Autofac的新手 我有像ServiceA.dll、ServiceB.dll等插件。配置Autofac容器时,我扫描当前目录中的Service*.dll,并从文件名中提取服务“A”、“B”的名称,并存储在名为serviceName的变量中。然后我找到实现IService的服务类的类型,并将其放入名为serviceType的变量中。每个服务还有一个名为Settings的配置设置类,因此我找到该类并将其类型放入名为serviceSettingsT

花了很长时间弄清楚如何让Autofac加载插件。我是Autofac的新手

我有像ServiceA.dll、ServiceB.dll等插件。配置Autofac容器时,我扫描当前目录中的Service*.dll,并从文件名中提取服务“A”、“B”的名称,并存储在名为serviceName的变量中。然后我找到实现IService的服务类的类型,并将其放入名为serviceType的变量中。每个服务还有一个名为Settings的配置设置类,因此我找到该类并将其类型放入名为serviceSettingsType的变量中。然后注册:

builder.RegisterType(serviceType)
  .Named<IService>(serviceName);
builder.RegisterType(serviceSettingsType)
  .Named<IServiceSettings>(serviceName+"Settings")
Autofac可以很好地实例化ServiceASettings类(它只是一个具有一个或多个属性的“数据类”),并将其传递给ServiceA的ctor

我搞不懂的是如何告诉Autofac,要创建一个ServiceASettings类以传递到ServiceA ctor,它需要实例化一个SettingsManager类,然后调用
var settings=wait Task ReadFromFile(string settingsFilename)
(其中t是ASettings类的类型)并在ServiceA的ctor调用中使用该设置类。正如上面的服务名称(示例中的“A”)是通过命令行确定的一样,传递给ReadFromFileAsync的settingsFilename需要在运行时传入

希望这是有意义的。我觉得我很快就可以用Autofac加载插件了,但就是无法找出服务的正确工厂调用或命名参数调用。有人用Autofac做过类似的事情吗?如果有助于使Autofac的工作更轻松,那么更改我的插件类和/或设置Manager类的体系结构的建议也非常受欢迎

编辑:

让它工作。我重新阅读了@cynic指向的页面,语法运行时参数终于为我点击了

将我的SettingsManager类更改为一个名为SettingsFile的类,该类接受类型、IFileSystem和带有文件名的字符串,并公开ReadSettings方法。登记册:

builder.Register((c, p) => new SettingsFile(
    c.Resolve<IFileSystem>(),
    p.Named<Type>("settingsType"),
    p.Named<string>("settingsFilename")))
    .As<ISettingsFile>();
builder.Register((c,p)=>新设置文件(
c、 Resolve(),
p、 命名(“设置类型”),
p、 命名(“设置文件名”))
.As();
决心:

var settingsName = "Service1Settigns";
var settingsType = scope.ResolveNamed<ISettings>(settingsName);
var settingsFile = scope.Resolve<ISettingsFile>(
    new NamedParameter("settingsType", settingsType.GetType()),
    new NamedParameter("settingsFilename", settingsFilename));
var settings = settingsFile.ReadSettings();
var settingsName=“service1settings”;
var settingsType=scope.ResolveNamed(settingsName);
var settingsFile=scope.Resolve(
新名称参数(“settingsType”,settingsType.GetType()),
新名称参数(“settingsFilename”,settingsFilename));
var settings=settingsFile.ReadSettings();
(我认为有一种方法可以让解析器为我调用ReadSettings,但还没有弄清楚。但我可能希望捕获错误并使用非常具体的错误消息进行增强。)

然后,在扫描插件DLL时,各种类被注册如下:

var assemblyTypes = assembly.GetTypes();
var settingsTypes = FindType(assemblyTypes, typeof(ISettings));
var settingsType = settingsTypes.First();
builder.RegisterType(settingsType).Named<ISettings>(settingsName);
var assemblyTypes=assembly.GetTypes();
var settingsTypes=FindType(assemblyTypes,typeof(ISettings));
var settingsType=settingsTypes.First();
builder.RegisterType(settingsType).Named(settingsName);
IService和IRepository也进行了类似的注册,下面介绍了如何启动客户机:

var client = scope.ResolveNamed<IClient>(clientName,
    new NamedParameter("settings", settings),
    new NamedParameter("repository", repository));
var client=scope.ResolveNamed(clientName,
新名称参数(“设置”,设置),
新命名参数(“存储库”,存储库));
这为我提供了一个基于clientName的IClient,在本例中,该clientName是在命令行上指定的(这是用于此客户端的适当设置文件路径)


开始真正喜欢Autofac的功能

通过简单浏览文档,我猜您希望在“服务”注册中使用
ResolvedParameter
,告诉它使用相应的“服务配置”-看看您尝试了什么?
var assemblyTypes = assembly.GetTypes();
var settingsTypes = FindType(assemblyTypes, typeof(ISettings));
var settingsType = settingsTypes.First();
builder.RegisterType(settingsType).Named<ISettings>(settingsName);
var client = scope.ResolveNamed<IClient>(clientName,
    new NamedParameter("settings", settings),
    new NamedParameter("repository", repository));