我在C#解决方案中使用Autofac作为依赖注入系统,该解决方案跨越多个类库和多个可执行文件。我使用模块来配置Autofac,但这仍然让我遇到构建DI容器的问题,这取决于我为其组成的可执行文件。
我尝试使用Autofac的RegisterAssemblyModules,但你必须给它一个要扫描的程序集列表,并且在使用类库程序集中的某些Type之前,程序集不会被加载,因此不会可以扫描。
有些人建议加载bin目录中的每个程序集,其中可能包含Autofac模块定义。但这似乎会导致不受欢迎的集会陷入行动的风险。
所以我想出的是这个静态类,它在一个公共类库中定义:
public static class Container
{
private static IContainer _instance;
private static Dictionary<string, Assembly> _moduleAssemblies = new Dictionary<string, Assembly>();
public static void RegisterAutofacModuleAssembly<T>()
where T : class
{
var assembly = typeof(T).Assembly;
if( !_moduleAssemblies.ContainsKey( assembly.FullName ) )
_moduleAssemblies.Add( assembly.FullName, assembly );
}
public static IContainer Instance
{
get
{
if( _instance == null )
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyModules( _moduleAssemblies.Select( ma => ma.Value ).ToArray() );
_instance = builder.Build();
}
return _instance;
}
}
}
您可以通过在应用程序的启动代码中包含这样的行来使用它:
public static void Main(string[] args)
{
AutoFacRegistrar.Container.RegisterAutofacModuleAssembly<ScannerApp>();
AutoFacRegistrar.Container.RegisterAutofacModuleAssembly<AppConfiguration>();
这是一个合理的解决方案吗?如果有一个更好,更灵活的人,我有兴趣了解它。
IOptions<>
绑定系统
在实施@ Nightowl888的建议时,我遇到了Microsoft配置IOptions<>
系统的问题。以下是我尝试配置Autofac来解析AppConfiguration对象的方法:
protected override void Load( ContainerBuilder builder )
{
base.Load( builder );
var config = new ConfigurationBuilder()
.AddJsonFile( AppConfiguration.WebJobsConfigFile, false )
.AddUserSecrets<ConfigurationModule>()
.AddEnvironmentVariables()
.Build();
builder.Register<AppConfiguration>( ( c, p ) =>
{
var retVal = new AppConfiguration( c.Resolve<ILogger>() );
config.Bind( retVal );
return retVal;
} )
.SingleInstance();
}
调用Bind()时出现问题。在遍历和解析配置信息时,它期望通过无参数构造函数创建各种对象......这使得构造函数注入很难使用。
如果我不能使用构造函数注入,我需要能够在构造函数代码中解析DI容器。我不知道如何定义一个在特定DI容器的解析语义中没有硬连接的库程序集。
思考?除了&#34;放弃IOptions<>
系统&#34;,我已经考虑过了,但它提供了许多我想维护的好处。
答案 0 :(得分:2)
每个可执行应用程序都应具有 拥有 唯一的DI配置。 Libraries和frameworks应该构建为对DI友好,但实际上并不引用任何DI容器。
组合根是应用程序的 配置 。在应用程序之间共享它类似于在应用程序之间共享.config
文件 - 也就是说,通常不会这样做。请参阅Composition Root Reuse。
如果您要使用autofac模块,它们应该是使用它们的应用程序的一部分,而不是包含在组件中的组件中。虽然看起来你不必在每个应用程序中重复配置代码而获得一些东西,但这样做的主要问题是它意味着你的应用程序失去了DI的一个主要好处 - 也就是说,它无法提供任何给定组件的替代实现。使库松散耦合的关键在于它允许决定如何将应用程序耦合在一起,最终由承载组件的应用程序进行。
宠物小便:另请注意,您拥有的项目或解决方案的数量与应用程序的运行时行为完全无关(例如它的组成方式)。项目和解决方案是一种在编译代码之前组织代码的方法 - 一旦编译代码,就没有“项目”或“解决方案”的概念,你剩下的只是“程序集”,可能依赖于其他“程序集” 。对于每个应用程序,您最终得到一个可执行文件程序集和0个或更多依赖程序集。组合根应该只存在于可执行程序集中。