Dynamic menu creation IoC

2019-03-06 06:42发布

问题:

I am wondering if anyone out there knows how I could create how could i use something like AutoFac to let me dynamically allow dll's to create there own forms and menu items to call them at run time.

So if I have an,

Employee.dll

  • New Starter Form
  • Certificate Form

Supplier.dll

  • Supplier Detail From
  • Products Form

In my winform app it would create a menu with this and when each one clicked load the relavent form up

People

  • New Starter
  • Certificate

Supplier

  • Supplier Details
  • Products

So I can add a new class library to the project and it would just add it to menu when it loads up.

Hope that make sense and someone can help me out.

Cheers

Aidan

回答1:

The first things you have to do is to make your core application extensible. Let's see a simple example.

You will have to allow your external assembly to create item entry in your main app. To do this you can create a IMenuBuilder interface in your main app.

public interface IMenuBuilder
{
    void BuildMenu(IMenuContainer container); 
}

This interface will allow external assembly to use a IMenuContainer to create MenuEntry. This interface can be defined like this :

public interface IMenuContainer 
{
    MenuStrip Menu { get; }
}

In your main form, you will have to implement IMenuContainer and call all the IMenuBuilder interface to allow them to create menu entry.

public partial class MainForm : Form, IMenuContainer
{
    public MenuStrip Menu 
    {
        get 
        {
           return this.mnsMainApp; 
        }
    }

    private void MainForm_Load(Object sender, EventArgs e)
    {
        ILifetimeScope scope = ... // get the Autofac scope
        foreach(IMenuBuilder menuBuilder in scope.Resolve<IEnumerable<IMenuBuilder>())
        {
            menuBuilder.BuildMenu(this); 
        }
    }
}

In each external assembly, you will have to implement as much IMenuBuilder as needed and one Autofac Module. In this module you will register those IMenuBuilder.

public class XXXModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<XXXMenuBuilder>()
               .As<IMenuBuilder>();
    }
}

Finally, in your core app, you will have to register all your modules provided by external assembly :

ContainerBuilder builder = new ContainerBuilder();
String path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

IEnumerable<Assembly> assemblies = Directory.GetFiles(path, "*.dll")
                                            .Select(Assembly.LoadFrom);

builder.RegisterAssemblyModules(assemblies);