RT , 近期开发Client端,希望通过插件式开发,降低耦合度说起来太高端,主要还是为了将需求变更的影响降低,为后续功能升级做好铺垫,通过加载dll的方式加载各个模块或页面,更新时主需要更新dll就好.
1.定义接口类
namespace Songqw.Net.Plugins.Interface
{
public interface IPluginMember
{
#region 基本属性
string PluginName();
int PluginId();
#endregion
#region 初始化
object InitPlugin();
object InitPlugin(object[] paras);
#endregion
#region 资源释放
bool DisposePlugin();
#endregion
}
}
2.做几个实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Songqw.Net.Plugins.Interface;
namespace Songqw.Net.Plugins.Test.PluginsPart1
{
public class PluginsPart1 : IPluginMember
{
public string PluginName()
{
return "PluginsPart1";
}
public int PluginId()
{
return GetHashCode();
}
public object InitPlugin()
{
throw new NotImplementedException();
}
public object InitPlugin(object[] paras)
{
throw new NotImplementedException();
}
public bool DisposePlugin()
{
throw new NotImplementedException();
}
}
}
...
using System;
using Songqw.Net.Plugins.Interface;
namespace Songqw.Net.Plugins.Test.PluginsPart2
{
public class PluginsPart2 : IPluginMember
{
public string PluginName()
{
return "PluginsPart2";
}
public int PluginId()
{
return GetHashCode();
}
public object InitPlugin()
{
throw new NotImplementedException();
}
public object InitPlugin(object[] paras)
{
throw new NotImplementedException();
}
public bool DisposePlugin()
{
throw new NotImplementedException();
}
}
}
......
3.通用的工具类
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Songqw.Net.Plugins.Tool
{
public class LoadLibrary
{
/// <summary>
/// 通过Type加载对象
/// 将识别Type和初始化Class 分开,避免识别时直接初始化.
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public static Object InitClassByType(Type type)
{
return type.Assembly.CreateInstance(type.FullName);
}
/// <summary>
/// 返回指定路径下的可加载插件对象数组.
/// </summary>
/// <param name="documentPath">指定的路径</param>
/// <returns>dll文件对象集合</returns>
public static Type[] LoadDocument(string documentPath)
{
if (Directory.Exists(documentPath) == false)
return null;
var members = new List<Type>();
//找到目录下的dll文件
String[] files = Directory.GetFiles(documentPath, @"*.dll");
if (files.GetLength(0) > 0)
{
for (int i = 0; i < files.GetLength(0); i++)
{
Type[] cs = LoadFiles(files[i]);
if (cs != null && cs.Length > 0)
{
members.AddRange(cs);
}
}
}
return members.ToArray();
}
/// <summary>
/// 返回指定路径的dll文件对象中包含的多个类对象
/// </summary>
/// <param name="filePath">指定的dll绝对路径</param>
/// <returns></returns>
public static Type[] LoadFiles(string filePath)
{
if (File.Exists(filePath) == false)
return null;
var asm = Assembly.LoadFrom(filePath);
return asm.GetTypes().Where(t => t.GetInterface("IPluginMember") != null).ToArray();
}
}
}
4. 最后,测试程序,及调用方法: 控制台应用.(新建一个控制台程序please)
using System;
using System.Windows.Forms;
using Songqw.Net.Plugins.Interface;
using Songqw.Net.Plugins.Tool;
namespace Songqw.Net.Plugins.Test.Main
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("启动插件测试 : 当前路径 {0} ", Application.StartupPath);
var plugins = LoadLibrary.LoadDocument(Application.StartupPath);
if (plugins != null && plugins.Length > 0)
{
Console.WriteLine("获取到插件数量 : {0} ", plugins.Length);
for (int index = 0; index < plugins.Length; index++)
{
var pluginMember = plugins[index];
Console.WriteLine("{0}. {1}", index, pluginMember.FullName);
}
while (true)
{
Console.WriteLine("Press num to init the plugins function , any char to exit");
try
{
var input = Console.ReadLine();
var select = Convert.ToInt32(input);
var selectPlugin = plugins[select];
if (selectPlugin != null)
{
var instance = LoadLibrary.InitClassByType(selectPlugin) as IPluginMember;
if (instance != null)
{
Console.WriteLine("Function Name : {0} ", instance.PluginName());
}
}
}
catch (Exception)
{
break;
}
}
}
else
{
Console.WriteLine("当前路径下没有符合条件的插件程序");
Console.WriteLine("Press any ket to exit");
Console.ReadKey();
}
}
}
}
代码基本都在这了, 我就不上传了, 我的结构是这样的: