我知道有很多关于使用MEF的构造函数参数注入的问题,但我的有点不同。
我想知道当我使用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>();
在上面的示例中,我只能使用ComposeExportedValue
一次,因为再次运行会导致ChangeRejectedException
。
所以,我的问题是:
SomeParam
的值吗?System.Collections.Concurrent.ConcurrentQueue
之类的东西,我在调用GetExportedValue
之前将参数值排入队列,然后在部件的构造函数中将值取列。但这是一个黑客攻击,也会产生比它解决的问题更多的问题。感谢您的帮助。 :)郎,问候,Yogesh Jagota
答案 0 :(得分:2)
如果上述两个问题的答案都是否定的,那么还有其他方法可以通过MEF和其他DI / IOC框架的组合实现这一目标吗?
我认为问题1和问题2的答案确实没有。
我会尝试AutoFac,它会为您提供更精细的控制和integrates with MEF。例如,它允许您设置这样的注册,以便Bar
和Baz
实例使用不同的参数获取其Foo
实例:
builder.Register(c => new Bar(new Foo(param));
builder.Register(c => new Baz(new Foo(param2));
答案 1 :(得分:1)
如果要在MEF中使用相同接口的不同实例(取决于某些逻辑(应用策略模式)),可以使用ExportMetadata Attribute。 例如,如果你有IDbManager,如果你有两个实现,那么就说一个Oracle和一个Sql 1.创建将保存元数据的元数据界面
public interface IDbManagerMetadata
{
DataProvider DataProvider { get; }
}
2。创建属性类,如下所示
[MetadataAttribute]
public class DbManagerMetadataAttribute : Attribute, IDbManagerMetadata
{
public DataProvider DataProvider { get; set; }
}
策略示例
public enum DataProvider { 甲骨文, SQL中, } [InheritedExport] 公共接口IDbManager { void Initialize(); }
[InheritedExport(typeof运算(IDbManager))] 公共类DbManager:IDbManager { public DbManager(DataProvider providerType) { _providerType = providerType; }
public void Initialize()
{
Console.WriteLine("provider : {0}", _providerType);
}
public DataProvider _providerType { get; set; }
}
两种不同的实现
[Export(typeof(IDbManager))]
[DbManagerMetadata(DataProvider = DataProvider.Oracle)]
public sealed class OracleDataProvider : DbManager
{
public OracleDataProvider():base(DataProvider.Oracle)
{
}
}
并且
[Export(typeof(IDbManager))]
[DbManagerMetadata(DataProvider = DataProvider.Sql)]
public sealed class SqlDataProvider : DbManager
{
public SqlDataProvider()
: base(DataProvider.Sql)
{
}
}
您可以使用我们在第一步中创建的元数据接口来决定使用哪一个,如下面的存储库所示
[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();
}
}