MEF中不使用特性如何配置ComposeExportedValue为非共享创建策略
问题根源
你使用ComposeExportedValue<ILogger>(_logger)方法注册时,传入的是已经初始化完成的固定_logger实例,MEF会将其作为全局共享的单例处理,所以所有导入位置拿到的都是同一个对象。
可行方案
方案1:自定义导出配置非共享生命周期(无侵入,无需修改现有导入代码)
无需给任何类加特性,直接通过CompositionBatch添加自定义导出,手动指定创建策略为非共享,每次导入时动态创建新的ILogger实例:
var batch = new CompositionBatch(); // 定义ILogger导出的元数据,指定非共享生命周期 var exportDefinition = new ExportDefinition( AttributedModelServices.GetContractName(typeof(ILogger)), new Dictionary<string, object> { { "ExportTypeIdentity", AttributedModelServices.GetTypeIdentity(typeof(ILogger)) }, { "System.ComponentModel.Composition.CreationPolicy", CreationPolicy.NonShared } }); // 导出委托每次被调用时返回新的ILogger实例,可替换为你自己的初始化逻辑 batch.AddExport(new Export(exportDefinition, () => new YourLoggerImpl())); // 提交注册到容器 container.Compose(batch);
这个方案完全兼容你现有构造函数注入ILogger的代码,所有导入位置每次都会自动拿到新实例。
方案2:封装初始化逻辑复用
如果你的Logger有固定的初始化参数,可以把创建逻辑封装为工厂委托,避免重复代码:
// 提前定义和你原有_logger完全一致的初始化逻辑 Func<ILogger> loggerFactory = () => { var newLogger = new YourLoggerImpl(); // 这里写你原本初始化_logger的所有配置逻辑 newLogger.SetLogLevel(LogLevel.Info); newLogger.SetOutputPath("./logs"); return newLogger; }; // 注册逻辑和方案1一致 var batch = new CompositionBatch(); var exportDefinition = new ExportDefinition( AttributedModelServices.GetContractName(typeof(ILogger)), new Dictionary<string, object> { { "ExportTypeIdentity", AttributedModelServices.GetTypeIdentity(typeof(ILogger)) }, { "System.ComponentModel.Composition.CreationPolicy", CreationPolicy.NonShared } }); batch.AddExport(new Export(exportDefinition, loggerFactory)); container.Compose(batch);
方案3:极简工厂注册(需少量修改导入代码)
如果可以接受调整导入侧代码,直接注册Func<ILogger>工厂,每次需要时主动获取新实例,代码量最少:
// 注册Logger工厂 container.ComposeExportedValue<Func<ILogger>>(() => new YourLoggerImpl()); // 导入侧修改构造函数即可 public class A { private readonly ILogger _logger; [ImportingConstructor] public A(Func<ILogger> loggerFactory) { // 调用工厂获取新实例 this._logger = loggerFactory(); } }
内容的提问来源于stack exchange,提问作者Dekel tsairi
相关产品推荐
相关产品推荐

