C# MEF:使用CreationPolicy.NonShared时将不同的构造函数参数传递给部件
我知道有很多关于使用MEF的构造函数参数注入的问题,但是我的有点不同 我想知道,当我使用C# MEF:使用CreationPolicy.NonShared时将不同的构造函数参数传递给部件,c#,dependency-injection,inversion-of-control,mef,C#,Dependency Injection,Inversion Of Control,Mef,我知道有很多关于使用MEF的构造函数参数注入的问题,但是我的有点不同 我想知道,当我使用PartCreationPolicy(CreationPolicy.NonShared)和GetExportedValue的组合时,有没有办法将不同的参数值传递给零件的构造函数 例如: [PartCreationPolicy(CreationPolicy.NonShared)] [Export] public partial class Foo { [ImportingConstructor]
PartCreationPolicy(CreationPolicy.NonShared)
和GetExportedValue
的组合时,有没有办法将不同的参数值传递给零件的构造函数
例如:
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export]
public partial class Foo
{
[ImportingConstructor]
public Foo([Import("SomeParam")]object parameter)
{
...
}
}
在别的地方
container.ComposeExportedValue("SomeParam", "Some value...");
var instance = container.GetExportedValue<Foo>();
container.ComposeExportedValue(“SomeParam”,“someValue…”);
var实例=container.GetExportedValue();
在上面的示例中,我只能使用ComposeExportedValue
一次,因为再次运行它将导致ChangeRejectedException
因此,我的问题是:
SomeParam
的值System.Collections.Concurrent.ConcurrentQueue
的内容,在调用GetExportedValue
之前,我将一个参数值排队,然后将该值从部件的构造函数中出列。但这是一种黑客行为,而且造成的问题比解决的问题还多问候,
约格什·贾戈塔 如果以上两个问题的答案都是否定的,那么有没有其他方法可以结合MEF和其他DI/IOC框架来实现这一点 我认为问题1和2的答案确实是否定的 我会尝试使用更细粒度的控件和。例如,它允许您像这样设置注册,以便
Bar
和Baz
实例使用不同的参数获取其Foo
实例:
builder.Register(c => new Bar(new Foo(param));
builder.Register(c => new Baz(new Foo(param2));
如果您想根据MEF中的某些逻辑(应用策略模式)使用同一接口的不同实例,请使用ExportMetadata属性。 例如,如果您有IDbManager,并且有两个实现,比如一个Oracle和一个Sql,那么 1.创建包含元数据的元数据接口
public interface IDbManagerMetadata
{
DataProvider DataProvider { get; }
}
二,。创建属性类,如下所示
[MetadataAttribute]
public class DbManagerMetadataAttribute : Attribute, IDbManagerMetadata
{
public DataProvider DataProvider { get; set; }
}
公共枚举数据提供程序
{
神谕
Sql,
}
[继承导出]
公共接口管理器
{
void初始化();
}
[InheriteExport(typeof(IDbManager))]
公共类DbManager:IDbManager
{
公共DbManager(数据提供程序提供程序类型)
{
_providerType=providerType;
}
公共无效初始化()
{
WriteLine(“提供程序:{0}”,_providerType);
}
公共数据提供程序_providerType{get;set;}
}
和两种不同的实现
[Export(typeof(IDbManager))]
[DbManagerMetadata(DataProvider = DataProvider.Oracle)]
public sealed class OracleDataProvider : DbManager
{
public OracleDataProvider():base(DataProvider.Oracle)
{
}
}
及
通过使用我们在第一步中创建的元数据接口,您可以决定使用哪一个,如下所示
[Export]
public class Repository
{
private IDbManager _dbManager;
private readonly IEnumerable<Lazy<IDbManager, IDbManagerMetadata>> DbManagers;
[ImportingConstructor]
public Repository([ImportMany(typeof(IDbManager))]IEnumerable<Lazy<IDbManager, IDbManagerMetadata>> dbManagers)
{
this.DbManagers = dbManagers;
var _dbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Oracle).Value;
}
public void Execute()
{
var oracleDbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Oracle).Value;
oracleDbManager.Initialize();
var sqlDbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Sql).Value;
sqlDbManager.Initialize();
}
}
[导出]
公共类存储库
{
私人IDbManager_dbManager;
私有只读IEnumerable数据库管理器;
[导入构造函数]
公共存储库([ImportMany(typeof(IDbManager))]IEnumerable DBManager)
{
this.DbManagers=DbManagers;
var_dbManager=DbManagers.First(x=>x.Metadata.DataProvider==DataProvider.Oracle).Value;
}
public void Execute()
{
var oracleDbManager=DbManagers.First(x=>x.Metadata.DataProvider==DataProvider.Oracle).Value;
oracledmanager.Initialize();
var sqlDbManager=DbManagers.First(x=>x.Metadata.DataProvider==DataProvider.Sql).Value;
sqlDbManager.Initialize();
}
}
我正在研究AutoFac/MEF集成,但在使用注册器ComposablePartCatalog时如何处理注册?我不能在这里使用注册
,因为它是由AutoFac自动完成的。我如何告诉AutoFac某个导出需要使用我提供的参数的非默认构造函数实例化,而不使用[ImportingConstructor]
?@Yogesh:您可以让一些组件注册到AutoFac(当您需要细粒度控制时),其他组件则使用MEF导出(当您需要动态发现插件时)。但对于同一个组件,您不能将两者混合使用。另一个选项是完全切换到AutoFac;您可以在需要时使用它来获得类似MEF的动态发现。它实际上是有效的。方法是使用IContainer
的Update
方法,该方法允许向现有容器添加新注册。谢谢。:)为不同实例设置具有不同值的ImportingConstructor参数的答案在哪里?@Sreenath dbmanagermetataAttribute是您的答案
[Export]
public class Repository
{
private IDbManager _dbManager;
private readonly IEnumerable<Lazy<IDbManager, IDbManagerMetadata>> DbManagers;
[ImportingConstructor]
public Repository([ImportMany(typeof(IDbManager))]IEnumerable<Lazy<IDbManager, IDbManagerMetadata>> dbManagers)
{
this.DbManagers = dbManagers;
var _dbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Oracle).Value;
}
public void Execute()
{
var oracleDbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Oracle).Value;
oracleDbManager.Initialize();
var sqlDbManager = DbManagers.First(x => x.Metadata.DataProvider == DataProvider.Sql).Value;
sqlDbManager.Initialize();
}
}