mef - how to make recomposition work automatically?
I've been trying to get recomposition to work but no luck... I tried many times and many approches - with no luck... can anyone point out my mistake? I expect that after I drop a new .dll into plugins directory the Senders collection will be automatically repopulated with new stuff...
//exported classes
[Export(typeof(ISender))]
public class SMTP : ISender
{
public string Name
{
get { return "SMTP plugin"; }
}
public void Send(string msg)
{
}
}
[Export(typeof(ISender))]
public class Exchange : ISender
{
public string Name
{
get { return "Exchange plugin"; }
}
public void Send(string msg)
{
// .. blah
}
}
/---------------------------------------------------------------------
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private const string STR_Pugins = ".\\plugins";
[ImportMany(typeof(ISender), AllowRecomposition = true)]
private List<ISender> Senders;
private DirectoryCatalog d;
CompositionContainer c;
public MainWindow()
{
InitializeComponent();
listBox1.DisplayMemberPath = "Name";
ConfigPlugins();
bindSenders();
}
private void ConfigPlugins()
{
DirectoryInfo dir = new DirectoryInfo(STR_Pugins);
if (!dir.Exists)
dir.Create();
d = new DirectoryCatalog(STR_Pugins);
d.Changed += new EventHandler<ComposablePartCatalogChangeEventArgs>(d_Changed);
c = new CompositionContainer(d);
c.ExportsChanged += new EventHandler<ExportsChangeEventArgs>(c_ExportsChanged);
c.ComposeParts(this);
}
void d_Changed(object sender, ComposablePartCatalogChangeEventArgs e)
{
bindSenders();
MessageBox.Show("d_Changed " + (Senders == null ? 0 : Senders.Count));
}
private void bindSenders()
{
listBox1.ItemsSource = Senders;
}
void c_ExportsChanged(object sender, ExportsChangeEventArgs e)
{
bindSenders();
MessageBox.开发者_JS百科Show("c_ExportsChanged "+ (Senders == null ? 0 : Senders.Count));
}
}
AFTER RESPONSE ok, I've added the refresh, but still I don't get why the listbox won't populate with the new data...
public partial class MainWindow : Window
{
private const string STR_Pugins = ".\\plugins";
[ImportMany(typeof(ISender), AllowRecomposition = true)]
private List<ISender> Senders;
DirectoryCatalog d;
CompositionContainer c;
public MainWindow()
{
InitializeComponent();
listBox1.DisplayMemberPath = "Name";
ConfigPlugins();
bindSenders();
}
private void ConfigPlugins()
{
DirectoryInfo dir = new DirectoryInfo(STR_Pugins);
if (!dir.Exists)
dir.Create();
d = new DirectoryCatalog(STR_Pugins);
c = new CompositionContainer(d);
c.ComposeParts(this);
}
private void bindSenders()
{
label1.DataContext = Senders;
listBox1.ItemsSource = Senders;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
d.Refresh();
bindSenders();
}
}
You have to call Refresh yourself. If you want you can use a FileSystemWatcher object to get notified when the directory contents have changed.
It won't repopulate because when the field is updated, a brand new List is set to the field. The existing collection is not modified. You have to set it up as a property instead of a field (you can still make it protected or private), then when the "set" is called, you update the listBox1.ItemsSource and the label1.DataContext.
精彩评论