MEF plugins have no data from host
I'm trying to put config data from host to plugins but I always get nulls at plugins. My code responsible for plugins is below:
Form:
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
DataStorage.Instance.LoadModes();
DataStorage.Instance.ActiveMode = "aaa";
DataStorage.Instance.RulesFile = "bbb";
DataStorage.Instance.SetProjectName("cccc");
DataStorage.Instance.LoadRules();
DataStorage.Instance.LoadPlugins();
}
}
DataStorage:
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(ConfigStorage))]
public class DataStorage: ConfigStorage
{
//fields and properties here
public string ActiveMode;
[ImportMany(typeof (IAPlugin))]
public IEnumerable<Lazy<IAPlugin, IAPluginData>> aPlugins;
[ImportMany(typeof (IBPlugin))]
public IEnumerable<Lazy<IBPlugin, IBPluginData>> bPlugins;
private CompositionContainer _container;
private sta开发者_StackOverflow中文版tic readonly DataStorage instance = new DataStorage();
static DataStorage()
{
}
private DataStorage()
{
Init();
}
public static DataStorage Instance
{
get { return instance; }
}
private void Init()
{
//code here
}
public void LoadPlugins()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(typeof(ConfigStorage).Assembly));
catalog.Catalogs.Add(new DirectoryCatalog(Settings.Default.GetPathFor("Plugins")));
_container = new CompositionContainer(catalog);
try
{
_container.ComposeParts(this);
}
catch (CompositionException compositionException)
{
Console.WriteLine(compositionException.ToString());
}
}
}
ConfigStorage:
public abstract class ConfigStorage
{
public string RulesFile;
public string ActiveMode;
//properties and methods
}
Plugin:
[Export(typeof (IAPlugin))]
[ExportMetadata("Name", "myNameIsBond")]
public class myNameIsBond : IAPlugin
{
protected readonly ConfigStorage configStorage;
[ImportingConstructor]
public myNameIsBond (ConfigStorage configStorage)
{
if (configStorage == null)
throw new ArgumentNullException("configStorage");
this.configStorage = configStorage;
}
public string DoStep(string url)
{
Console.WriteLine(configStorage.ActiveMode); //this is null - it should be "aaa"
return url;
}
}
When I run plugin.Value.DoStep("sth"); the Console.WriteLine(configStorage.ActiveMode); always print null - when I debugging: all fields from configStorage are nulls. What I'm doing wrong? How can I put DataStorage instance to my plugins?
I think the problem is that the ConfigStorage export is showing up in the catalog, so the imports are getting satisfied with a version created by the catalog instead of the singleton you have configured. Try putting a PartNotDiscoverableAttribute on the DataStorage class.
As an aside, your DataStorage constructor is private, but it looks like the catalog can still create a separate version of it because the constructor is invoked through reflection.
I typically don't use an instance variable at all and just let MEF create the singleton, but if you really want to have an instance property you can do something like
// note that there is no export attribute here
public class DataStorage: ConfigStorage
{
[Export(typeof(ConfigStorage))]
public static DataStorage instance { get; private set; }
}
So that MEF will export your singleton instance rather than creating a new object.
精彩评论