BrnShop开源网上商城第三讲:插件的工作机制
http://www.cnblogs.com/wheretime/p/3809404.html
using System;
using System.IO;
using System.Web;
using System.Reflection;
using System.Web.Compilation;
using System.Collections.Generic;
[assembly: PreApplicationStartMethod(typeof(BrnShop.Core.BSPPlugin), "Load")]
namespace BrnShop.Core
{
/// <summary>
/// BrnShop插件管理类
/// </summary>
public class BSPPlugin
{
private static object _locker = new object();//锁对象
private static string _installedfilepath = "/App_Data/InstalledPlugin.config";//插件安装文件
private static string _pluginfolderpath = "/Plugins";//插件目录
private static string _shadowfolderpath = "/Plugins/bin";//插件影子目录
private static List<PluginInfo> _oauthpluginlist = new List<PluginInfo>();//开放授权插件列表
private static List<PluginInfo> _paypluginlist = new List<PluginInfo>();//支付插件列表
private static List<PluginInfo> _shippluginlist = new List<PluginInfo>();//配送插件列表
private static List<PluginInfo> _uninstalledpluginlist = new List<PluginInfo>();//未安装插件列表
/// <summary>
/// 开放授权插件列表
/// </summary>
public static List<PluginInfo> OAuthPluginList
{
get { return _oauthpluginlist; }
}
/// <summary>
/// 支付插件列表
/// </summary>
public static List<PluginInfo> PayPluginList
{
get { return _paypluginlist; }
}
/// <summary>
/// 配送插件列表
/// </summary>
public static List<PluginInfo> ShipPluginList
{
get { return _shippluginlist; }
}
/// <summary>
/// 未安装插件列表
/// </summary>
public static List<PluginInfo> UnInstalledPluginList
{
get { return _uninstalledpluginlist; }
}
/// <summary>
/// 加载插件程序集到应用程序域中
/// </summary>
public static void Load()
{
try
{
//插件目录
DirectoryInfo pluginFolder = new DirectoryInfo(IOHelper.GetMapPath(_pluginfolderpath));
if (!pluginFolder.Exists)
pluginFolder.Create();
//插件bin目录
DirectoryInfo shadowFolder = new DirectoryInfo(IOHelper.GetMapPath(_shadowfolderpath));
if (!shadowFolder.Exists)
{
shadowFolder.Create();
}
else
{
//清空影子复制目录中的dll文件
foreach (FileInfo fileInfo in shadowFolder.GetFiles())
{
fileInfo.Delete();
}
}
//获得安装的插件系统名称列表
List<string> installedPluginSystemNameList = GetInstalledPluginSystemNameList();
//获得全部插件
List<KeyValuePair<FileInfo, PluginInfo>> allPluginFileAndInfo = GetAllPluginFileAndInfo(pluginFolder);
foreach (KeyValuePair<FileInfo, PluginInfo> fileAndInfo in allPluginFileAndInfo)
{
FileInfo pluginFile = fileAndInfo.Key;
PluginInfo pluginInfo = fileAndInfo.Value;
if (String.IsNullOrWhiteSpace(pluginInfo.SystemName))
throw new BSPException(string.Format("插件'{0}'没有\"systemName\", 请输入一个唯一的\"systemName\"", pluginFile.FullName));
if (pluginInfo.Type < 0 || pluginInfo.Type > 2)
throw new BSPException(string.Format("插件'{0}'不属于任何一种类型, 请输入正确的的\"type\"", pluginFile.FullName));
//加载插件dll文件
FileInfo[] dllFiles = pluginFile.Directory.GetFiles("*.dll", SearchOption.TopDirectoryOnly);
foreach (FileInfo dllFile in dllFiles)
{
//部署dll文件
DeployDllFile(dllFile, shadowFolder);
}
if (IsInstalledlPlugin(pluginInfo.SystemName, installedPluginSystemNameList))//安装的插件
{
//根据插件类型将插件添加到相应列表
switch (pluginInfo.Type)
{
case 0:
_oauthpluginlist.Add(pluginInfo);
break;
case 1:
_paypluginlist.Add(pluginInfo);
break;
case 2:
_shippluginlist.Add(pluginInfo);
break;
}
}
else//未安装的插件
{
_uninstalledpluginlist.Add(pluginInfo);
}
}
}
catch (Exception ex)
{
throw new BSPException("加载BrnShop插件时出错", ex);
}
}
/// <summary>
/// 安装插件
/// </summary>
/// <param name="systemName">插件系统名称</param>
public static void Install(string systemName)
{
lock (_locker)
{
if (string.IsNullOrWhiteSpace(systemName))
return;
//在未安装的插件列表中获得对应插件
PluginInfo pluginInfo = _uninstalledpluginlist.Find(x => x.SystemName.Equals(systemName, StringComparison.InvariantCultureIgnoreCase));
//当插件为空时直接返回
if (pluginInfo == null)
return;
//当插件不为空时将插件添加到相应列表
switch (pluginInfo.Type)
{
case 0:
_oauthpluginlist.Add(pluginInfo);
_oauthpluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
break;
case 1:
_paypluginlist.Add(pluginInfo);
_paypluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
break;
case 2:
_shippluginlist.Add(pluginInfo);
_shippluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
break;
}
//在未安装的插件列表中移除对应插件
_uninstalledpluginlist.Remove(pluginInfo);
//将新安装的插件保存到安装的插件列表中
List<string> installedPluginSystemNameList = GetInstalledPluginSystemNameList();
installedPluginSystemNameList.Add(pluginInfo.SystemName);
SaveInstalledPluginSystemNameList(installedPluginSystemNameList);
}
}
/// <summary>
/// 卸载插件
/// </summary>
/// <param name="systemName">插件系统名称</param>
public static void Uninstall(string systemName)
{
lock (_locker)
{
if (string.IsNullOrEmpty(systemName))
return;
PluginInfo pluginInfo = null;
Predicate<PluginInfo> condition = x => x.SystemName.Equals(systemName, StringComparison.InvariantCultureIgnoreCase);
pluginInfo = _oauthpluginlist.Find(condition);
if (pluginInfo == null)
pluginInfo = _paypluginlist.Find(condition);
if (pluginInfo == null)
pluginInfo = _shippluginlist.Find(condition);
//当插件为空时直接返回
if (pluginInfo == null)
return;
//根据插件类型移除对应插件
switch (pluginInfo.Type)
{
case 0:
_oauthpluginlist.Remove(pluginInfo);
break;
case 1:
_paypluginlist.Remove(pluginInfo);
break;
case 2:
_shippluginlist.Remove(pluginInfo);
break;
}
//将插件添加到未安装插件列表
_uninstalledpluginlist.Add(pluginInfo);
//将卸载的插件从安装的插件列表中移除
List<string> installedPluginSystemNameList = GetInstalledPluginSystemNameList();
installedPluginSystemNameList.Remove(pluginInfo.SystemName);
SaveInstalledPluginSystemNameList(installedPluginSystemNameList);
}
}
/// <summary>
/// 编辑插件信息
/// </summary>
/// <param name="systemName">插件系统名称</param>
/// <param name="friendlyName">插件友好名称</param>
/// <param name="description">插件描述</param>
/// <param name="displayOrder">插件排序</param>
public static void Edit(string systemName, string friendlyName, string description, int displayOrder)
{
lock (_locker)
{
bool isInstalled = true;//是否安装
PluginInfo pluginInfo = null;
Predicate<PluginInfo> condition = x => x.SystemName.Equals(systemName, StringComparison.InvariantCultureIgnoreCase);
pluginInfo = _oauthpluginlist.Find(condition);
if (pluginInfo == null)
pluginInfo = _paypluginlist.Find(condition);
if (pluginInfo == null)
pluginInfo = _shippluginlist.Find(condition);
//当插件为空时直接返回
if (pluginInfo == null)
{
pluginInfo = _uninstalledpluginlist.Find(condition); ;
//当插件为空时直接返回
if (pluginInfo == null)
return;
else
isInstalled = false;
}
pluginInfo.FriendlyName = friendlyName;
pluginInfo.Description = description;
pluginInfo.DisplayOrder = displayOrder;
//将插件信息持久化到对应文件中
IOHelper.SerializeToXml(pluginInfo, IOHelper.GetMapPath("/Plugins/" + pluginInfo.Folder + "/PluginInfo.config"));
//插件列表重新排序
if (isInstalled)
{
switch (pluginInfo.Type)
{
case 0:
_oauthpluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
break;
case 1:
_paypluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
break;
case 2:
_shippluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
break;
}
}
else
{
_uninstalledpluginlist.Sort((first, next) => first.DisplayOrder.CompareTo(next.DisplayOrder));
}
}
}
/// <summary>
/// 获得安装的插件系统名称列表
/// </summary>
private static List<string> GetInstalledPluginSystemNameList()
{
return (List<string>)IOHelper.DeserializeFromXML(typeof(List<string>), IOHelper.GetMapPath(_installedfilepath));
}
/// <summary>
/// 保存安装的插件系统名称列表
/// </summary>
/// <param name="installedPluginSystemNameList">安装的插件系统名称列表</param>
private static void SaveInstalledPluginSystemNameList(List<string> installedPluginSystemNameList)
{
IOHelper.SerializeToXml(installedPluginSystemNameList, IOHelper.GetMapPath(_installedfilepath));
}
/// <summary>
/// 获得全部插件
/// </summary>
/// <param name="pluginFolder">插件目录</param>
/// <returns></returns>
private static List<KeyValuePair<FileInfo, PluginInfo>> GetAllPluginFileAndInfo(DirectoryInfo pluginFolder)
{
List<KeyValuePair<FileInfo, PluginInfo>> list = new List<KeyValuePair<FileInfo, PluginInfo>>();
FileInfo[] PluginInfoes = pluginFolder.GetFiles("PluginInfo.config", SearchOption.AllDirectories);
Type pluginType = typeof(PluginInfo);
foreach (FileInfo file in PluginInfoes)
{
PluginInfo info = (PluginInfo)IOHelper.DeserializeFromXML(pluginType, file.FullName);
list.Add(new KeyValuePair<FileInfo, PluginInfo>(file, info));
}
list.Sort((firstPair, nextPair) => firstPair.Value.DisplayOrder.CompareTo(nextPair.Value.DisplayOrder));
return list;
}
/// <summary>
/// 判断插件是否已经安装
/// </summary>
/// <param name="systemName">插件系统名称</param>
/// <param name="installedPluginSystemNameList">安装的插件系统名称列表</param>
/// <returns> </returns>
private static bool IsInstalledlPlugin(string systemName, List<string> installedPluginSystemNameList)
{
foreach (string name in installedPluginSystemNameList)
{
if (name.Equals(systemName, StringComparison.InvariantCultureIgnoreCase))
return true;
}
return false;
}
/// <summary>
/// 部署程序集
/// </summary>
/// <param name="dllFile">插件程序集文件</param>
/// <param name="shadowFolder">/Plugins/bin目录</param>
private static void DeployDllFile(FileInfo dllFile, DirectoryInfo shadowFolder)
{
DirectoryInfo copyFolder;
//根据当前的信任级别设置复制目录
if (WebHelper.GetTrustLevel() != AspNetHostingPermissionLevel.Unrestricted)//非完全信任级别
{
copyFolder = shadowFolder;
}
else//完全信任级别
{
copyFolder = new DirectoryInfo(AppDomain.CurrentDomain.DynamicDirectory);
}
FileInfo newDllFile = new FileInfo(copyFolder.FullName + "\\" + dllFile.Name);
try
{
File.Copy(dllFile.FullName, newDllFile.FullName, true);
}
catch
{
//在某些情况下会出现"正由另一进程使用,因此该进程无法访问该文件"错误,所以先重命名再复制
File.Move(newDllFile.FullName, newDllFile.FullName + Guid.NewGuid().ToString("N") + ".locked");
File.Copy(dllFile.FullName, newDllFile.FullName, true);
}
Assembly assembly = Assembly.Load(AssemblyName.GetAssemblyName(newDllFile.FullName));
//将程序集添加到当前应用程序域
BuildManager.AddReferencedAssembly(assembly);
}
}
}

浙公网安备 33010602011771号