花了很多时间弄清楚如何让 Autofac 加载插件。我是 Autofac 的新手。
我有像 ServiceA.dll、ServiceB.dll 等插件。在配置我的 Autofac 容器时,我扫描当前目录中的 Service*.dll 并从文件名和存储中提取服务“A”、“B”的名称在名为 serviceName 的变量中。然后我找到实现 IService 的服务类的类型并将其放入名为 serviceType 的变量中。每个服务还有一个名为 <serviceName>Settings 的配置设置类,因此我找到该类并将其类型放在名为 serviceSettingsType 的变量中。然后注册:
builder.RegisterType(serviceType)
.Named<IService>(serviceName);
builder.RegisterType(serviceSettingsType)
.Named<IServiceSettings>(serviceName+"Settings")
Run Code Online (Sandbox Code Playgroud)
构建 Autofac 配置后,我可以获得如下服务类型:
scope.ResolveNamed<IService>("A");
Run Code Online (Sandbox Code Playgroud)
并且很快,类 ServiceA 被实例化。但是,ServiceA 需要一个 ctor 参数:
public class ServiceA(ServiceASettings settings) {}
Run Code Online (Sandbox Code Playgroud)
Autofac 很好地实例化了一个 ServiceASettings 类(它只是一个具有一个或多个属性的“数据类”)并将其传递到 ServiceA 的构造函数中。
我无法弄清楚的是如何告诉 Autofac 创建一个 ServiceASettings 类以传递到 ServiceActor 它需要实例化一个 SettingsManager 类然后调用var settings = await Task<T> ReadFromFile(string settingsFilename)(其中 T 是 ASettings 类的类型)并使用该设置类在 ServiceA 的 ctor 调用中。就像上面的服务名称(示例中的“A”)是从命令行确定的一样,传递给 ReadFromFileAsync 的 settingsFilename 需要在运行时传入。
希望这是有道理的。我觉得我已经非常接近使用 Autofac 加载插件了,但就是无法为 Service ctor 找出正确的工厂调用或命名参数调用。有人用 Autofac 做过类似的事情吗?更改插件类和/或 SettingsManager 类架构的建议也非常受欢迎,如果它有助于使用 Autofac 使这项工作更容易。
编辑:
得到这个工作。我重新阅读了@cynic 指向的页面,最终为我点击了语法运行时参数。
将我的 SettingsManager 类更改为一个名为 SettingsFile 的类,它采用一个类型、一个 IFileSystem 和一个带有文件名的字符串并公开一个 ReadSettings 方法。登记:
builder.Register((c, p) => new SettingsFile(
c.Resolve<IFileSystem>(),
p.Named<Type>("settingsType"),
p.Named<string>("settingsFilename")))
.As<ISettingsFile>();
Run Code Online (Sandbox Code Playgroud)
解决:
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();
Run Code Online (Sandbox Code Playgroud)
(我认为有一种方法可以让解析器为我调用 ReadSettings,但还没有弄清楚。但无论如何,我可能想要捕获错误并使用非常具体的错误消息进行增强。)
然后在扫描插件 DLL 时,各种类被注册如下:
var assemblyTypes = assembly.GetTypes();
var settingsTypes = FindType(assemblyTypes, typeof(ISettings));
var settingsType = settingsTypes.First();
builder.RegisterType(settingsType).Named<ISettings>(settingsName);
Run Code Online (Sandbox Code Playgroud)
对 IService 和 IRepository 进行了类似的注册,以下是客户端的启动方式:
var client = scope.ResolveNamed<IClient>(clientName,
new NamedParameter("settings", settings),
new NamedParameter("repository", repository));
Run Code Online (Sandbox Code Playgroud)
这为我提供了一个基于 clientName 的 IClient,在这种情况下,它是在命令行上指定的(为此客户端使用的适当设置文件路径也是如此)。
开始真正喜欢 Autofac 的功能!
| 归档时间: |
|
| 查看次数: |
731 次 |
| 最近记录: |