20170807-20170813C#工作学习周总结
在.NET中,程序集是进行部署,版本控制的基本单元。System.Reflection命名空间中的Assembly类型,代表了一个程序集。并包含了关于程序集的信息。
win32程序开发流程
windows程序分为“程序代码”和“UI”资源两大部分,两大部分最后以RC编译器整合为一个完整的exe档案。
需要什么函数库(.LIB)
动态链接库:引用程序所调用的windows API函数是在“执行时期”才链接上的。
并不是扩展名是dll的才是动态链接库,事实上.exe,.dll,.fon,.mod,.drv,.ocx都是所谓的动态链接库。
需要什么头文件
以消息为基础,以事件驱动之
接受并处理消息的主角就是窗口。每一个窗口都应该有一个函数负责处理消息,程序员必须负责设计这个所谓的“窗口函数”。程序员必须负责设计这个所谓的“窗口函数”。如果窗口获得一个消息,则这个窗口函数必须判断消息的类别,决定处理的方式。
程序进入点WinMain
当Windows的外壳shell侦测到使用者欲执行一个Windows程序,于是调用加载器把该程序加载,然后调用C startup code,后者再调用WinMain,开始执行程序。WinMain的四个参数由操作系统传递进来。
回调函数(什么是回调函数)
你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。(作者:常溪玲链接:https://www.zhihu.com/question/19801131/answer/13005983来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。)
对话框的运行
Windows的对话框依其与父窗口的关系,可分为两类:
- “令其父窗口失效,直到对话框结束”,这种称为modal对话框;
- “父窗口与对话框共同运行”,这种称为modeless对话框。
资源描述文件
RC文件是一个以文字描述资源的地方
SDK程序
指以Windows raw API完成的程序
核心对象
核心对象是系统的一种资源,系用对象一旦产生,任何应用程序都可以开启并使用该对象,系统给予核心对象一个计数值作为管理之用。核心对象包括:event,mutex,semaphore,file,file-mapping,process,thread
虚函数
从操作型定义来看,什么是虚函数?如果你预期派生类有可能重新定义某一个成员函数,那么你就在基类中把此函数设为virtual
。MFC有两个十分重要的虚函数:与document有关的Serialize函数和与view
有关的OnDraw
函数。应该在自己的CMyDoc和CMyView中改写这两个虚函数。
纯虚拟函数不需定义其实际动作,它的存在只是为了在衍生类别中被重新定义,只是为了提供一个多态接口。只要是拥有纯虚拟函数的类别,就是一种抽象类别,它是不能够被具象化(instantiate)的,也就是说,你不能根据它产生一个对象(你怎能说一种形状为’Shape’ 的物体呢)。
■ 如果你期望衍生类别重新定义一个成员函数,那么你应该在基础类别中把此函数设为virtual。
■ 以单一指令唤起不同函数,这种性质称为Polymorphism,意思是” the ability to assume many forms “,也就是多态。
■ 虚拟函数是C++ 语言的Polymorphism性质以及动态绑定的关键。
■ 既然抽象类别中的虚拟函数不打算被调用,我们就不应该定义它,应该把它设为纯虚拟函数(在函数声明之后加上” =0” 即可)。
■ 我们可以说,拥有纯虚拟函数者为抽象类别(abstract Class ),以别于所谓的具象类别(concrete class ) 。
■ 抽象类别不能产生出对象实体,但是我们可以拥有指向抽象类别之指针,以便于操作抽象类别的各个衍生类别。
■ 虚拟函数衍生下去仍为虚拟函数,而且可以省略virtual关键词。
多态
编译器无法在编译时期判断pEmp -> computePay到底是调用哪一个函数,必须在执行时期才能评估之,这称为后期绑定late binding 或动态绑定dynamic binding。
C++ Template Functions
函数声明:
template <class T> T power (T base,int exponent);
T power(T base,int exponent);
容易让人迷惑的是其中的”class”字眼,它其实并不一定表示C++的class,它也可以是一个普通的数据类型。不过是表示:T是一种普通类型,而此一类型将在调用此函数时才给予。
构造式和析构式
所谓构造式(constructor),就是对象诞生后第一个执行(并且是自动执行)的函数,它的函数名称必定要与类别名称相同。
相对于构造式,自然就有个析构式(destructor),也就是在对象行将毁灭但未毁灭之前一刻,最后执行(并且是自动执行)的函数,它的函数名称必定要与类别名称相同,再在最前面加一个~ 符号。
一个有着阶层架构的类别群组,当衍生类别的对象诞生之时,构造式的执行是由最基础类别(most based)至最尾端衍生类别(most derived);当对象要毁灭之前,析构式的执行则是反其道而行。
RTTI运行类型识别
具备IsKindOf的能力,能在执行期侦测某个对象是否“属于某种类”,并传回True或False。
消息映射(Message Mapping)
将消息与表格(消息映射表——Message Map)中的元素比较,然后调用对应的处理程序,这种操作我们也称为消息映射。
XML文件的C#读取
在程序中访问进而操作XML文件一般有两种模型,分别是使用DOM(文档对象模型)和流模型,使用DOM的好处在于它允许编辑和更新XML文档,可以随机访问文档中的数据,可以使用XPath查询,但是,DOM的缺点在于它需要一次性的加载整个文档到内存中,对于大型的文档,这会造成资源问题。流模型很好的解决了这个问题,因为它对XML文件的访问采用的是流的概念,也就是说,任何时候在内存中只有当前节点,但它也有它的不足,它是只读的,仅向前的,不能在文档中执行向后导航操作。
使用XmlDocument是一种基于文档结构模型的方式来读取XML文件.在XML文件中,我们可以把XML看作是由文档声明(Declare),元素(Element),属性(Attribute),文本(Text)等构成的一个树.最开始的一个结点叫作根结点,每个结点都可以有自己的子结点.得到一个结点后,可以通过一系列属性或方法得到这个结点的值或其它的一些属性.
1: xn 代表一个结点
2: xn.Name;//这个结点的名称
3: xn.Value;//这个结点的值
4: xn.ChildNodes;//这个结点的所有子结点
5: xn.ParentNode;//这个结点的父结点
1.1 读取所有的数据.
使用的时候,首先声明一个XmlDocument对象,然后调用Load方法,从指定的路径加载XML文件.
1: XmlDocument doc = new XmlDocument();
2: doc.Load(@"..\..\Book.xml");
然后可以通过调用SelectSingleNode得到指定的结点,通过GetAttribute得到具体的属性值.参看下面的代码
// 得到根节点bookstore
XmlNode xn = xmlDoc.SelectSingleNode("bookstore");
// 得到根节点的所有子节点
XmlNodeList xnl = xn.ChildNodes;
foreach (XmlNode xn1 in xnl)
{
BookModel bookModel = new BookModel();
// 将节点转换为元素,便于得到节点的属性值
XmlElement xe = (XmlElement)xn1;
// 得到Type和ISBN两个属性的属性值
bookModel.BookISBN = xe.GetAttribute("ISBN").ToString();
bookModel.BookType = xe.GetAttribute("Type").ToString();
// 得到Book节点的所有子节点
XmlNodeList xnl0 = xe.ChildNodes;
bookModel.BookName=xnl0.Item(0).InnerText;
bookModel.BookAuthor=xnl0.Item(1).InnerText;
bookModel.BookPrice=Convert.ToDouble(xnl0.Item(2).InnerText);
bookModeList.Add(bookModel);
}
dgvBookInfo.DataSource = bookModeList;
在正常情况下,上面的代码好像没有什么问题,但是对于读取上面的XML文件,则会出错,原因就是因为我上面的XML文件里面有注释,大家可以参看Book.xml文件中的第三行,我随便加的一句注释.注释也是一种结点类型,在没有特别说明的情况下,会默认它也是一个结点(Node).所以在把结点转换成元素的时候就会报错.”无法将类型为“System.Xml.XmlComment”的对象强制转换为类型“System.Xml.XmlElement”。”
幸亏它里面自带了解决办法,那就是在读取的时候,告诉编译器让它忽略掉里面的注释信息.修改如下:
XmlDocument xmlDoc = new XmlDocument();
XmlReaderSettings settings = new XmlReaderSettings();
settings.IgnoreComments = true;//忽略文档里面的注释
XmlReader reader = XmlReader.Create(@"..\..\Book.xml", settings);
xmlDoc.Load(reader);
最后读取完毕后,记得要关掉reader.
1: reader.Close();
这样它就不会出现错误.
1.2C#读取XML中元素和属性的值(XmlDocument读取Xml)
反射
什么是反射:
1.在程序运行时,
动态获取 加载程序集
动态获取 类型(类,接口)
动态获取 类型的成员 信息(字段,属性,方法)
2.在运行时,
动态创建类型实例,以及调用和访问这些实例成员
程序集
程序集是代码进行编译是的一个逻辑单元,把相关的代码和类型进行组合,然后生成PE文件(例如可执行文件.exe
和类库文件.dll
)。由于程序集在编译后并不一定会生成单个文件,而可能会生成多个物理文件,甚至可能会生成分布在不同位置的多个物理文件,所以程序集是一个逻辑单元,而不是一个物理单元。即程序集在逻辑上是一个编译单元,但在物理储存上可以有多种存在形式。对于静态程序集可以生成单个或多个文件,而动态程序集是存在于内存中的。在C#中程序集处处可见,因为任何基于.NET
的代码在编译时都至少存在一个程序集(所有.NET
项目都会默认引用mscorlib
程序集)
类库编译成程序集
在bin
目录下生成.dll
或。.exe
程序集包含哪些内容:
类型元数据【以二进制的形式,描述代码中定义的每一个类型和成员】
程序集元数据【程序集清单,版本号,名称等】
IL代码【这些都被装在exe或dll中】
资源文件
反射中要用到动态链接库作为插件,需要声明一个程序集来接收。
Type类
反射中用到的最重要的一种类型就是type类,System.Type
类对于反射起着核心的作用。当反射请求加载的类型时,公共语言运行库将为它创建一个 Type
。可以使用Type
对象的方法、字段、属性和嵌套类来查找有关该类型的所有信息。
接口
为了规范插件的行为,需要主程序开发者编写接口,统一操作类型及对象。
加载程序集常用到的方法示例:
private void LoadPlugins()
{
// 1.加载plugins目录下的所有的dll文件
string plugins = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "plugins");
// 1.1 搜索plugins目录下的所有的dll文件
string[] dlls = Directory.GetFiles(plugins, "*.dll");
// 2.循环将每个dll文件都加载起来
foreach (string dllPath in dlls)
{
// 2.1 动态加载当前循环的dll文件
Assembly assembly = Assembly.LoadFile(dllPath);
// 2.2 获取当前dll中的所有的public类型
Type[] types = assembly.GetExportedTypes();
// 2.3 获取IEditor接口的Type
Type typeIEditor = typeof(IEditor);
for (int i = 0; i < types.Length; i++)
{
// 2.4 验证当前的类型即实现了IEditor接口并且该类型还可以被实例化
if (typeIEditor.IsAssignableFrom(types[i]) && !types[i].IsAbstract)
{
IEditor editor = (IEditor) Activator.CreateInstance(types[i]);
// 2.5 向菜单栏中动态添加一个菜单项
ToolStripItem toolItem = 编辑ToolStripMenuItem.DropDownItems.Add(editor.PluginName);
// 2.6 为刚刚增加的菜单项注册一个单击事件
toolItem.Click += new EventHandler(toolItem_Click);
toolItem.Tag = editor;
}
}
}
}
private void toolItem_Click(object sender, EventArgs e)
{
ToolStripItem item = sender as ToolStripItem;
if (item != null)
{
if (item.Tag != null)
{
IEditor editor = item.Tag as IEditor;
if (editor != null)
{
// 运行该插件
editor.Execute(this.textBox1);
}
}
}
}
其中,接口代码如下:
public interface IEditor
{
string PluginName
{
get;
}
void Execute(TextBox txtbox);
}
网上的一篇不错的总结:
待补充…
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)