C# 程序中 对象所处的上下文环境
起因:
近来,我在业余时间忙于开发一个 网站后台自动生成软件——软件的设计开发起因会有另外的文章进行介绍;
现在是 2011-1-154:40 (我已经累计有 超过 13个夜晚都是奋战到这个时候的——为了这个软件);
软件的架构思路,参照公司的标准产品 SUF6.1 的架构模式;
最完美的是,该软件支持 插件扩展——任何人相对软件的扩展,都不需要修改源代码——只需要标注特性,那么程序就会加载你的 第三方 工具栏,右键菜单 等选项;
问题的起因就在插件这一块!
我在软件的主体部分通过接口BaseFile, IPageType
创建了一个 插件中的对象
EditPageType e.aspx
ListPageType l.aspx
右键单击这个 对象节点,
“文件属性”——这个数据来自 主程序的实现;
“配置窗体”——这个来自 插件 WebCreate.Forever.dll
然后,我将程序序列化保存,然后再反序列化——结果,这个 节点的 “配置窗体”不见了;
这个对象是否可以使用这个 右键菜单项 有一个 判断函数
——这段代码是说,如果 WebObject(网站对象) 不为空,且 这个对象是 插件的 EditPageType 类,那么就表示这个对象可以 使用这个 右键菜单项 ,返回 True(真);
查错:
这个右键菜单去哪了?为什么不显示这个菜单?
——后来查错原因,代码行是
我调试了一哈,但是 obj 明显就是 EditPageType 的数据结构,没理由这个代码返回在False啊!
于是我写下这行代码,进行强行转换!
结果,我遇到了一个以前都没有遇到的异常:
之后在一个form上使用这个控件,打开这个控件的属性修改NumRange属性,Ctrl+S保存的时候会报错
报错内容为:
Code generation for property 'NumRange' failed. Error was:'[A]WinForm.NumberScope cannot be cast to [B]WinForm.NumberScope. Type Aoriginates from 'WinForm, Version=1.0.0.0, Culture=neutral,PublicKeyToken=null' in the context 'LoadNeither' at location'C:\Users\CHUNSIBO\AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies\elgwjxaa01\WinForm.exe'.Type B originates from 'WinForm, Version=1.0.0.0, Culture=neutral,PublicKeyToken=null' in the context 'LoadNeither' at location'C:\Users\ss\AppData\Local\Microsoft\VisualStudio\10.0\ProjectAssemblies\ko-pdm2_01\WinForm.exe'.'
——简单的说,这异常的 意思是说 :
ListPageType 对象 l.aspx 不是 ListPageType;
——这就好比说 人类 的对象 不是 人类 一样;
不过,这个异常也很清楚:他的意思也很明确,这个 ListPageType和 ListPageType 是不一样的;
我最后仔细思考,明白了原因:这个对象的创建 是 在 主程序中创建的;
而现在,我想在 插件 的方法中转换 主程序的 对象,这时就出错了;
比方说:每个人都有身份证;
舒小龙也有一个 身份证,我们可以说的身份证 是 身份证;
但是有一天,去了美国 ,这时 的身份证 是 身份证 美国就不承认这句话是对的了;
舒小龙强行转换,硬是要说这个身份证是身份证——于是美国的工作人员就报了一个异常:这个 身份证 和 身份证 是不一样的;
问题的症结在于 上下文环境 的不一样:中国 和 美国;
就像上面说的,创建对象是说 主程序的环境 Default 中创建,但是我想 在LoadNeither 环境下使用他一样!!
解决方案:
我之前的 WebObject 类是 继承Iserializable——准备进行手动序列化的,但是后来 我觉得手动序列化很麻烦,包括子类都难以幸免;所以,我又取消了这计划;
——如果,手动序列化能不能 避免这个问题呢?
我没有尝试这个,因为;昨晚好不容易将手动序列化的 代码 改成 系统的序列化,我再反一次,我岂不是有病;
第二个想法:既然问题出在:Default 中创建,就不能在LoadNeither 中使用;
那么,能不能将 创建的过程 也转移到 插件中,就是 LoadNeither 环境中?
——不可能,因为创建的过程有很多界面在联动工作,主程序是最需要数据的地方,数据的创建如果转移到了 插件中,那么失去这个插件,主程序就会崩溃!且 以后另外的插件 在 主程序中找不到 公共部分,那么岂不是 其他的插件也要 重新编写 创建数据的编码?
那么能不能将 插件 的环境 弄得 和 主程序 一样呢?
那样,主程序 和 插件 都能够共享数据,不会有 环境限制;
——是的,这才是最好的办法,最简单,最省力!且依然维护了软件最初的架构设计初衷!
----------------------------------------------------------------------------------------------------------------------------------------------------------------
话说回来,我的插件 是在 程序的 最开始就执行加载的——加载参数在 配置文件中!
代码简化如下:
——也就是将 WebCreate.Forever.dll WebCreate.Action.dll 这两个插件加载到程序中;
但是,没想到,系统加载这两个插件程序集时,居然将这两个放到了 别的环境下;——典型的歧视!
如何让系统加载这两个程序集时,将其 划归到 默认环境下呢?
我突然想起了 彬哥(我们项目经理)之前的一篇文章可能涉及如何加载程序集;
——原来 加载程序集的方法有这么多;
我试了一下,结果 正确的做法 正是 第一种:
Assembly.Load("WebCreate.Action"); Assembly.Load("WebCreate.Forever");
不过 加载的是 程序集的 命名空间,而不是程序集名称,应该只是当时彬哥写文章时的一个表示而已;
好了,问题就此解决!
感想:
今天的异常 是我一直写程序 所没有遇到过的,很兴奋!
所以,先将程序放下来,写下这篇感想与领悟!