连载-基于插件技术的GIS应用框架(C# + ArcEngine9.3)(五)
[align=center]基于插件技术的GIS应用框架(C# + ArcEngine9.3)(五)--------------------------插件初始化(1)[/align]
在第四节中,我们论及了插件的XML保存格式,对于各个XML节点的属性也有了一个大概的了解,下面,我们就如何利用DevExpress套件就这些插件的加载进行详细的剖析。首先,我们必须从已经编译好的DLL中获取插件的类型信息,这就需要利用C#所提供的反射机制。
一、插件的反射
/// 根据反射机制产生插件对象并将其放入插件池
public class PluginActivator
{
/// 定义插件文件所在路径
private static readonly string pluginpath = System.Windows.Forms.Application.StartupPath;
/// 获取插件并加入到插件池
public static PluginCollection ActivatePluginsFromDll()
{
//存储插件的容器
PluginCollection _PluginCol = new PluginCollection();
//获得插件文件夹中的每一个dll文件
string[] _files = Directory.GetFiles(pluginpath, "*.dll");
foreach (string _pluginfile in _files)
{
Assembly _assembly = Assembly.LoadFrom(_pluginfile );
if (_assembly != null)
{
Type[] _types = null;
try
{
_types = _assembly.GetTypes();
}
catch (ReflectionTypeLoadException ex)
{
}
finally
{
foreach (Type _type in _types)
{
//获得一个插件对象的接口信息
Type[] _Inte易做图ceList = _type.GetInte易做图ces();
//遍历接口
foreach (Type Inte易做图ceType in _Inte易做图ceList)
{
//将插件添加到相应的插件池中
switch (Inte易做图ceType.FullName)
{
case "AxeMap.PluginEngine.Inte易做图ce.IAxCommand":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxTool":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxEdit":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxCombobox":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxColorPicker":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxSubItem":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxContentsView":
GetPlugin(_PluginCol, _type);
break;
case "AxeMap.PluginEngine.Inte易做图ce.IAxDockableWindowDef":
GetPlugin(_PluginCol, _type);
break;
default:
break;
}
}
}
}
}
}
return _PluginCol;
}
关于如何反射对象,C#提供了很多的例子,具体就不再叙述,下面我们将结合DevExpress套件重点介绍各类插件的加载过程。
二、插件的初始化
1.Command插件
private DevExpress.XtraBars.BarButtonItem CreateUICommand(IAxCommand cmd, string itemnamespace, string customcaption)
{
if (cmd == null)
{
return null;
}
(cmd as ICommand).OnCreate(_App); //调用esriSystemUI.ICommand插件的OnCreate,将框架对象传递给插件对象
BarButtonItem UICmd = new BarButtonItem(); //产生一个UI层的按钮对象,并根据插件的属性进行相应设置
UICmd .Hint = (cmd as ICommand).Tooltip;
if (customcaption != "")
{
UICmd .Caption = customcaption; //优先显示插件配置文件中插件的标题
}
else
{
UICmd .Caption = (cmd as ICommand).Caption;
}
//加载命令插件的bitmap或icon
System.IntPtr _Handle = (System.IntPtr)(cmd as ICommand).Bitmap;
if (_Handle.ToInt32() != 0)
{
try
{
UICmd .Glyph = System.Drawing.Bitmap.FromHicon(_Handle);
}
catch
{
UICmd.Glyph = System.Drawing.Image.FromHbitmap(_Handle);
}
}
UICmd.Enabled = (cmd as ICommand).Enabled;
if ((cmd as ICommand).Checked)
{
UICmd .ButtonStyle = BarButtonStyle.Check;
}
//记录命令插件的类型到 Tag 属性
UICmd.Tag = cmd.ToString();
//记录命令插件的Category属性,由于使用DevExpress,设置UICmd的分类很麻烦,这是DevExpress的不好用的地方
IEnumerator categoryEnum = _barManager.Categories.GetEnumerator();
string cmdCategory;
categoryEnum.Reset();
while (categoryEnum.MoveNext() == true)
{
cmdCategory = ((BarManagerCategory)categoryEnum.Current).ToString();
if (cmdCategory == (cmd as ICommand).Category)
{
UICmd.Category = (BarManagerCategory)categoryEnum.Current;
break;
}
}
//委托事件
UICmd.ItemClick += new ItemClickEventHandler(UICmd_Click);
//将生成的UICmd添加到CommandManager中,DevExpress提供一个统一管理器,管理所有的工具条对象
_barManager.Items.AddRange(new DevExpress.XtraBars.BarItem[] { UICmd});
_UIControlList.Add(itemnamespace, UICmd);
return UICmd;
}
2.ICombobox插件(以编辑任务列表为例)
编辑任务列表的插件实现:
namespace AxeMap.MapEdit
{
public class EditTasks : IAxCombobox
{
private AxeMapEngine.Inte易做图ce.IAxApplication _App;
private string _EditTask;
private List<string> _EditTaskList = null;
public EditTasks()
{
_EditTaskList = new List<string>();
_EditTaskList.Add("新建要素");
_EditTaskList.Add("分割要素");
_EditTaskList.Add("自动闭合多边形");
}
#region IAxCombobox 成员
public string Name
{
get { return "EditTasks"; }
}
public string Caption
{
get { return "编辑任务"; }
}
public bool ShowCaption
{
get { return true; }
}
public System.Collections.ICollection Items
{
get { return _EditTaskList; }
}
public string Text
{
get
{
if (_App.MapEngine.IsBeingEdited)
{
return _EditTask;
}
else
{
return "";
}
}
}
public string Category
{
get { return "编辑"; }
}
public bool Enabled
{
get
{
return ((_App.MapEngine.IsBeingEdited) && (_App.MapEngine.CurrentFeatureLayer != null));
}
}
public bool Editable //用户只能从列表中选择,不能修改列表
{
get { return false; }
}
public int Width //列表显示多宽
{
get { return 186; }
}
public int DropDownRows
{
get { return 9; }
}
public string Tooltip
{
get { return "编辑任务"; }
}
public string Message
{
get { return "编辑任务"; }
}
public void OnKeyPress()
{
}
public void OnKeyDown()
{
}
public void EditValueChanged(string newText)
{
_EditTask = newText;
if (_EditTask == "")
{
_App.MapEngine.CurrentEditTask = null;
}
else
{
_App.MapEngine.CurrentEditTask = null;
switch (_EditTask)
{
case "": _App.MapEngine.SetEditTask(""); break;
case "新建要素": _App.MapEngine.SetEditTask("Create New Feature"); break;
case "分割要素": _App.MapEngine.SetEditTask("Cut Features"); break;
case "自动闭合多边形": _App.MapEngine.SetEditTask("Auto Complete Polygon"); break;
default: _App.MapEngine.SetEditTask("Create New Feature"); break;
}
}
}
private void WorkspaceEvents_OnStartEditing()
{
_EditTask = _EditTaskList.ToArray().GetValue(0).ToString();
EditValueChanged(_EditTask);
}
private void WorkspaceEvents_OnStopEditing(bool bSave)
{
_EditTask = "";
EditValueChanged(_EditTask);
}
public void OnCreate(AxeMapEngine.Inte易做图ce.IAxApplication hook)
{
if (hook != null)
{
this._App = hook; //获取框架程序对象
_App.MapEngine.WorkspaceEvents.OnStartEditing += new AxWorkspaceStartEditingEventsHandler(WorkspaceEvents_OnStartEditing); //通过事件代理响应框架中当前编辑工作空间的事件
_App.MapEngine.WorkspaceEvents.OnStopEditing += new AxWorkspaceStopEditingEventsHandler(WorkspaceEvents_OnStopEditing);
}
}
#endregion
}
}
--------------------编程问答-------------------- ArcEngine对象间的关系是相当的不明确.. --------------------编程问答-------------------- 连载还未结束 ,看完最后结果,您再做评价。框架不是用来说明ArcEngine对象间的关系的,这点你要搞清楚。 --------------------编程问答-------------------- 没分发帖了,有兴趣的哥们去我博客看吧, 我在那发,如若未能访问CSDN的博客,那就去 http://blog.sina.com.cn/burningnight --------------------编程问答-------------------- 楼主辛苦了 --------------------编程问答-------------------- CSDN博客里 将大致的设计思路和核心部分的一些代码,诸如自己实现捕捉、编辑任务列表、编辑图层列表及草图工具的代码都贴了出来,有兴趣可以研究一下,其实几个接口综合起来研究,并不难。之前试用delphi 来实现的,后来我照搬了原来的实现,区别在与c#在处理IActiveView事件和IWorkspace的事件可以更简单,事实证明用C#确实不错,不过运行起来,感觉比delphi版本的要慢,这是显而易见的了。
补充:企业软件 , 地理信息系统