代码改变世界

.net使用外部程序集拓展功能

2013-05-24 13:28  无聊玩博客  阅读(173)  评论(0编辑  收藏  举报

以windows窗体应用程序为例。

第一步,建立一个程序集,它包含能将插件插入可拓展windows窗体应用程序中的类型。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommonSnappableTypes
{
    //为可插入拓展windows窗体应用程序的所有插件提供一个多态接口
    public interface IAppFunction
    {
        void Doit();
    }
    //顺便提一个特性
    [AttributeUsage(AttributeTargets.Class)]
    public class CompanyInfoAttribute:System.Attribute
    {
        public string CompanyName{get;set;}
        public string CompanyUrl{get;set;}
    }
}

2.构建插件

需要建立一个实现IAppFunction接口的类型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CommonSnappableTypes;

namespace CSharpSnapIn
{
    [CompanyInfo(CompanyName="My Company",CompanyUrl="www.MyCompany.com")]
    public class CsharpModule : IAppFunction
    {
        public void Doit()
        {
           MessageBox.Show("Your have just used the C# snap in!");
        }
    }
}

3.构建可拓展的Windows Froms应用程序

界面代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using CommonSnappableTypes;

namespace MyExtendApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();           
        }

        private void snapInModuleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                if (dlg.FileName.Contains("CommonSnapTypes"))
                {
                    MessageBox.Show("CommonSnapTypes has no snap-ins!");
                }
                else if(!LoadExternalModule(dlg.FileName))
                {
                     MessageBox.Show("Nothing implements IAppFunction!");
                }
            }
        }
        private bool LoadExternalModule(string path)
        {
            bool found = false;
            Assembly asm = null;
            try
            {
                asm = Assembly.LoadFrom(path);//加载程序集(插件)
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
                return false;
            }        
            var theClassTypes = from t in asm.GetTypes()
                                where t.IsClass && t.GetInterface("IAppFunction") != null
                               select t;
            foreach (var t in theClassTypes)
            {
                found = true;
                IAppFunction iApp = asm.CreateInstance(t.FullName, true) as IAppFunction;
                iApp.Doit();
                listBox1.Items.Add(t.FullName);
                DisplayCompanyData(t);
            }
            return found;
        }
        private void DisplayCompanyData(Type t)
        {
            var comInfos = from info in t.GetCustomAttributes(false)
                          where info.GetType() == typeof(CompanyInfoAttribute)
                          select info;
            foreach (CompanyInfoAttribute info in comInfos)
            {
                MessageBox.Show(info.CompanyUrl, info.CompanyName);
            }
        }
    }
}