views:

1003

answers:

3

Hi,

I'm designing an application that supports plugin development. Its more of a learning exercise.

I've come across a problem I don't know how to solve.

All of the assemblies (plugins) being loaded into my app contain a showPrefs() method. As I load each assembly, I want to assign a button to each one so that when I click on the button, it triggers the showPrefs() method of the assembly that the button is assigned to.

How do I do this? A quick and dirty solution would be to change the showPrefs() method signature to be showPrefs(object sender, EventArgs e). This way I can assign it to the button but I think this is a cheap workaround around.

Any ideas people?

+4  A: 

I think you need to clarify what you're talking about, as what you're asking is much less complicated than loading the assemblies in the first place.

After you're done with the assembly loading, you'll have a list of types that implement your interface. Simply iterate through, creating buttons for each and, in the click event handler for the button, run your showPrefs method.

Here's some c# pseudocode:

Button b;
foreach(var i in instancesThatHavePrefsMethods)
{
  b = new Button();
  b.Click += (o,e) => { i.showPrefs(); };
  this.Children.Add(b);
}

Once I have the types, I can instantiate one of each, holding on to them. Then all I need to do is create a button for each, add an event handler (the enclosure created by the lambda in the pseudocode holds the reference to the correct instance; you can alternatively create your own class to do this or mandate an event handler in your interface), and then add the button to your form.


From your clarification, there are a couple different ways to do this.

First, mandate an event handler on your interface thusly:

public interface IPluginKLol
{
  //snip

  ///<summary>An event handler, when fired, calls <seealso cref="showPerfs"/></summary>
  void ShowPerfsEventHandler(object o, EventArgs e);

  //snip again
}

and then

Button b;
IEnumerable<IPluginKLol> instancesThatHavePrefsMethods = GetPlugins();
foreach(var i in instancesThatHavePrefsMethods)
{
  b = new Button();
  b.Click += i.ShowPerfsEventHandler;
  this.Children.Add(b);
}

Alternately, you can create a class to translate the event to calling showPerfs (just instantiate, set your reference, and assign the event handler):

public class ShowPerfsBroker
{
  public IPluginKLol Victim {get;set;}

  public void ShowPerfsEventHandler(object o, EventArgs e)
  {
    if(Victim == null) return;
    Victim.ShowPerfs();
  }
}
Will
A: 

The click event handler only accepts delegates that have the method signature of (object o, EventArgs e) so I don't know how I would assign the showPrefs() method to the click event.

Thats the bit I'm having trouble with.

Sir Psycho
K, I get it. Updating...
Will
+2  A: 

If you look at Will's pseudocode, he assigns a lambda expression to the Click handler, like such:

b.Click += (o,e) => { i.showPrefs(); };

That's an anynomous method right there, accepting an object and EventArgs. It then calls your showPrefs function on the interface. It's roughly equal to the following:

b.Click += delegate(Object o, EventArgs e) { i.showPrefs(); };

Which might be useful if you're using c# 2.0.

Erik van Brakel
+1 I think this answer goes nicely with Wills.
John_
This answer is the simplest to implement although I also like Wills. Thanks heaps guys.
Sir Psycho