开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜