• .NET 基础知识


    .net程序基本编写、执行流程(c#)
          1>编写c#代码,保存为.cs文件。
          2>通过csc.exe程序来将.cs文件编译为.net程序集(.exe或.dll)。此时的exe或dll并不是机器码(cpu不可理解)。【>csc /out:c:a.exe c:program.cs】   C:WindowsMicrosoft.NETFrameworkv4.0.30319csc.exe
          3>程序运行时通过JIT编译(Just In Time)即时编译,将程序集编译为cpu能理解的机器码,这时cpu才能执行。(这个编译过程会与当前机器有关(根据当前机器的内存、cpu等))。

    垃圾回收

    垃圾回收器,只回收托管堆中的内存资源,不回收其他资源(数据库连接、文件句柄、网络端口等)。
    •没有变量引用的对象。没有变量引用的对象,表示可以被回收了(null),断了线的风筝,再也回不来了。
    •回收时间不确定,当程序需要新内存的时候开始执行回收。
    •GC.Collect();//手动调用垃圾回收器。不建议使用,垃圾回收时会暂停一下(非常短暂)让程序自动去GC。
     
    垃圾回收器中“代”的概念:
    •共3代:第0代、第1代、第2代。
    •各代的回收频率:第0代最高,其次第1代,再次第2代。也就是说越老的对象生存几率越大。
    .net中垃圾回收机制:mark-and-compact(标记和压缩),一开始假设所有对象都是垃圾。
    除了内存资源外的其他资源怎么办?~或者Dispose()

    最基本的5个设计原则

    单一职责原则(SRP:Single Responsibility Principle):一个类,应该仅有一个引起它变化的原因,不要将变化原因不同的职责封装在一起,而应该隔离。

    开放封闭原则(OCP,Open Closed Principle):软件实体应当对修改关闭,对扩展开放。

    依赖倒置原则(DIP,Dependency Inversion Principle):依赖抽象,而不要依赖于具体,因为抽象相对稳定。

    接口隔离原则(ISP,Interface Segregation Principle): 尽量应用专门的接口,而不是单一的总接口,接口应该面向用户,将依赖建立在最小的接口上。

    Liskov替换原则(LSP,Liskov Substitution Pinciple): 子类必须能够替换其基类。

    合成/聚合复用原则(CARP,Composite/Aggregate Reuse Principle)在新对象中聚合已有对象,使之成为新对象的成员,从而通过操作这些对象达到复用的目的。合成方式较继承方式耦合更松散,所以应该少继承。

    •接口→抽象类→父类→具体类(在定义方法参数、返回值、声明变量的时候能用抽象就不要用具体。)
     
    params 可变参数  
    ·一个函数中只能一个参数带params关键字;
    ·带params关键字的参数必须是最后一个参数;
    ·带params关键字的参数类型必须是一维数组(传递一个或者多个参数);

    类中的成员,如果不加访问修饰符,则默认为private

    类如果不加访问修饰符,则默认为internal

    继承:

    ---好处

    1.代码重用

    2.多态(里氏替换原则LSP)

    ---特征

    1.当写好一个类以后,默认会存在一个没有参数的构造函数(即便我们不写构造函数,也会存在这么一个无参的构造函数)

    2.当手动添加一个构造函数以后,会将默认的无参数的构造函数覆盖掉。

    3.类的构造函数是不能被继承的。只能在子类中去调用父类的构造函数。 

    编译是为父类对象,但运行却是一个子类对象。具体特征如下:
      1.被声明为父类对象
      2.拥有父类属性
      3.占用子类的内存空间
      4.子类方法覆盖父类的方法时,此时对象调用的是子类的方法;否则,自动调用继承父类的方法.

    抽象类和接口的区别

    接口定义类的公共行为,抽象类定义类的公共实现

    一个类只能继承自一个类(抽象类),但是可以同时实现多个接口

    接口中不能有实现,抽象类中可以有未实现成员也可以有实现的成员

    接口中未实现的方法必须在子类中实现,抽象类中未实现的成员必须在子类中重写

    好的接口定义应该是具有专一功能性的,而不是多功能的,否则造成接口污染。如果一个类只是实现了这个接口的中一个功能,而不得不去实现接口中的其他方法,就叫接口污染。   

    什么时候使用抽象类,什么时候使用接口

      抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。

    1.飞机会飞,鸟会飞,他们都继承了同一个接口“飞”;但是F22属于飞机抽象类,鸽子属于鸟抽象类。
    2. 就像铁门木门都是门(抽象类),你想要个门我给不了(不能实例化),但我可以给你个具体的铁门或木门(多态);而且只能是门,你不能说它是窗(单继承);一个门可以有锁(接口

    虚方法和抽象方法的区别

    虚方法必须有实现(哪怕是空实现),抽象方法必须没有实现

    抽象方法必须在抽象类中声明,虚方法可以出现在抽象类中

    抽象方法必须在子类中重写,虚方法可以被重写

    实现多态的主要手段:

    1.虚方法virtual

    2.抽象方法abstract

    3.接口。

    关于虚方法需要注意的几点:

    1.父类中如果有方法需要让子类重写,则可以将该方法标记为virtual

    2.虚方法在父类中必须有实现,哪怕是空实现。

    3.虚方法子类可以重写(override),也可以不重写。

        public abstract class MyBase
        {
    
           protected abstract void Search();
    
            
            protected virtual void Save()
            {
             dbContent.SaveChange();
            }
        }
    

    static  

    普通类中的静态成员static
      •只能通过类名访问
      •静态方法中只能访问静态成员,或通过对象访问实例成员。(就像main方法)
      •多个对象共享同一个静态成员。
    class Program
        {
            static void Main(string[] args)
            {
                Person p = new Person();
                p.Name = "张三";
                Person.age = 18;
                Test t = new Test();
                t.MyMethod();
                Console.WriteLine(p.Name);
                Console.WriteLine(Person.age);
                Console.ReadKey();
            }
        }
    View Code
    静态类(一般都用作工具类,里面都是一些工具函数)
      •Math、Console、Convert 等都是静态类。
      •静态类中只能包括静态成员
      •静态构造函数不能有参数、不能有访问修饰符(默认为private)。静态构造函数在第一次使用该静态类的时候只执行一次。
     
    l静态成员属于类所有,非静态成员属于类的实例所有
    lC#静态方法属于类所有,类实例化前即可使用
    l在实例方法中可以直接调用静态方法,在静态方法中不可以直接调用实例方法
    l静态方法和静态变量创建后始终使用同一块内存(静态存储区),而使用实例的方式会创建多个内存
    l少使用静态类,静态类、静态成员所分配的内存在程序退出时才会释放。
     
    l1.在实例类中使用静态成员。
    •账户类:(实例类)
    •class Account
    •{
    •UserName //用户名
    •Address //地址
    •Total //存款额
    •static Rate //利率,由于该银行采用浮动利率,每天的利率根据当天的挂牌利率(基准利率)来计算,所以“利率”不适合作为每个对象单独的一个数据。
    •}//当多个对象共享同一个数据的时候就可以在实例类中加入静态成员。
     
    l2.使用静态类
    •在项目中需要频繁用到的一些工具类,例如:Math、Console、Convert 等。或者模拟“全局变量”的时候。
     
    多态:为了程序的可扩展性。
    l多态的作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
    lis-a:可以用来验证继承关系中是否合理。(can do,验证实现接口是否合理*)
    lif(obj is 类型A)//obj是父类类型对象,”类型A”是子类类型。
    l关键字as (类型转换)、 is(通常类型转换前需要通过is来判断一下类型。)
     
    实现多态的方式:
    1.virtual,子类重写父类中的方法。
    2.abstract,子类重写父类中的方法。(抽象类中可以有实例成员也可以有抽象成员。)抽象的父类或者接口如果子类没有实现其方法是不能创建父类对象的。
    3.接口,接口中的所有成员必须被子类中全部实现,除非子类是抽象类,把接口中的成员标记为抽象的。接口中可以有属性、方法、索引器等(本质上也是方法),但不能有字段(因为字段是实现)
     
     
    enum

    enum Gender { Male,Female}

    把字符串转换成枚举Gender g = (Gender)Enum.Parse(typeof(Gender), "Male");

    struct

    就是小类,值类型,不能继承类,可以实现接口,不能有显示无参构造函数(隐式),除非字段被声明为 const 或 static,否则无法初始化.

    结构体适合一些小型数据结构,这些数据结构包含的数据以创建结构后不修改的数据为主。例如:struct类型适于表示Point、Rectangle和Color等轻量对象。

    由于结构的副本由编译器自动创建和销毁(结构必须要在实例化前对其内的成员变量进行初始化),因此不需要使用默认构造函数析构函数。实际上,编译器通过为所有字段赋予默认值来实现默认构造函数

    String字符串的一些特性:

    不可变性(ToUpper演示)
    字符串暂存池(拘留池)(针对字符串常量)
    •内部维护一个哈希表key为字符串,value是地址。每次为一个新变量赋值都会找key中是否有,如果有则直接把value中的地址赋值给新变量
    •对于动态字符串本身在哈希表中没有,通过Intern可以添加到该哈希表中,目的为了提高性能。
    •String.Intern(xx), Intern 方法使用暂存池来搜索与 str 值相等的字符串。如果存在这样的字符串,则返回暂存池中它的引用。如果不存在,则向暂存池添加对 str 的引用,然后返回该引用。
    •String.IsInterned(xx),此方法在暂存池中查找 str。如果已经将 str 放入暂存池中,则返回对此实例的引用;否则返回 nullNothingnullptrnull 引用

    StringBuilder

    StringBuilder仅仅是拼接字符串的工具,大多数情况下还需要把StringBuilder转换为String.

    Equals、==、ReferenceEquals方法

    •string的Equals方法判断的是字符串的内容是否相同(重写了Object中的Equals方法。)
    •而object中的Equals方法是判断对象的地址是否相同
    •查看String类的==运算符,内部调用的也是Equals
    •判断两个对象是否相同:object. object.ReferenceEquals();
     

    数组

    数组特点:类型统一、长度固定。

    Array是所有数组的父类。

     
    集合
    常用集合
    •“类似数组”集合:ArrayList(可变长度,类型任意,无论什么类型的数据放到ArrayList中以后都变成了Object类型,取出的数据需要类型转换,非泛型)、List<T>(泛型)
    •“键值对”集合(“哈希表”集合):Hashtable(非泛型)、Dictionary<K,V>(泛型)
    •“堆栈”集合:Stack、Stack<T>(LIFO)
    •“队列”集合:Queue、Queue<T>(FIFO)
    •“可排序键值对”集合:(插入、检索没有“哈希表”集合高效)
    •SortedList、SortedList<K,V> (占用内存更少,可以通过索引访问)
    •SortedDictionary<K,V> (占用内存更多,没有索引,但插入、删除元素的速度比SortedList快)
    •Set 集合:无序、不重复。HashSet<T>,可以将 HashSet类视为不包含值的 Dictionary集合。与List<T>类似。SortedSet<T>(.net4.0支持,有序无重复集合)
    •“双向链表”集合:LinkedList<T>,增删速度快。

    System.Collections.Specialized 命名空间包含专用的和强类型的集合,例如,链接的列表词典、位向量以及只包含字符串的集合。

    System.Collections.Concurrent 命名空间提供多个线程安全集合类。当有多个线程并发访问集合时,应使用这些类代替 System.Collections 和 System.Collections.Generic 命名空间中的对应类型。 

    键值对集合原理示意图

    装箱、拆箱

    必须是: 值类型→引用类型  或  引用类型→值类型。

    拆箱时,必须用装箱时的类型来拆箱

    文件操作常用相关类

    File                  //操作文件,静态类,对文件整体操作。拷贝、删除、剪切等。
    Directory         //操作目录(文件夹),静态类。
    DirectoryInfo    //文件夹的一个“类”,用来描述一个文件夹对象(获取指定目录下的所有目录时返回一个DirectoryInfo数组。)
    FileInfo            //文件类,用来描述一个文件对象。获取指定目录下的所有文件时,返回一个FileInfo数组。
    Path                //对文件或目录的路径进行操作(很方便)【字符串】
    Stream            //文件流,抽象类。
    •FileStream      //文件流,MemoryStream(内存流),NetworkStream(网络流)
    •StreamReader //快速读取文本文件
    •StreamWriter  //快速写入文本文件
    •GZipStream
     
    Path类(对字符串操作)
    目录和文件操作的命名控件System.IO
    string ChangeExtension(string path, string extension) (*)
    •修改文件的后缀,“修改”支持字符串层面的,没有真的给文件改名
    •string s = Path.ChangeExtension(@"C: empF3.png", "jpg")
    string Combine(string path1, string path2)
    •将两个路径合成一个路径,比用+好,可以方便解决不加斜线的问题,自动处理路径分隔符的问题
    •string s = Path.Combine(@"c: emp","a.jpg")
    string GetDirectoryName(string path) (*)
    •得到文件的路径名。Path.GetDirectoryName(@"c: empa.jpg")
    string GetExtension(string path) 得到文件的扩展名
    string GetFileName(string path) 得到文件路径的文件名部分
    string GetFileNameWithoutExtension(string path) 得到去除扩展名的文件名
    string GetFullPath(string path) 得到文件的全路径。可以根据相对路径获得绝对路径。
    string GetTempFileName()  得到一个唯一的临时文件名(*)
    string GetTempPath() 得到临时文件夹的路径(*)
     
    操作目录(Directory)
    为了实现目录树,所以要掌握读取目录的类
    Directory和DirectoryInfo
    •void Delete(string path, bool recursive)     删除目录, recursive表示是否递归删除,如果recursive为false则只能删除空目录
    •bool Exists(string path)      判断目录是否存在
    •string[] GetDirectories(string path)  得到一个目录下的子目录
    •string[] GetDirectories(string path, string searchPattern, SearchOption searchOption)    通配符查找目录下的子目录,可以搜索到隐藏文件。
    •static string[] GetFiles(string path)  得到一个目录下的文件
    •string[] GetFiles(string path, string searchPattern, SearchOption searchOption)   通配符查找目录下的文件
    •DirectoryInfo GetParent(string path)  得到目录的父目录
    •move()  //移动、剪切。只能在同一个磁盘中。目录没有Copy方法。可以使用Move()方法实现重命名。
    •create()
     
    StreamWriter(读取文本文件)
    Stream把所有内容当成二进制来看待,如果是文本内容,则需要程序员来处理文本和二进制之间的转换。
    用StreamWriter可以简化文本类型的Stream的处理
    StreamWriter是辅助Stream进行处理的

     using (StreamWriter writer = new StreamWriter(stream, encoding))

     {

          writer.WriteLine("你好");

     }

    面试题)深度拷贝。浅层拷贝。先手写浅层拷贝、深层拷贝的代码,理解了概念再谈用MemberwiseClone 、DeepCopy。见备注
    写代码拷贝,实现ICloneable方法,内部调用MemberwiseClone  
    
    参考资料http://www.cnblogs.com/liping13599168/archive/2007/07/28/834242.html 
     
    static object DeepCopy(object src)
            {
                BinaryFormatter Formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
                using (MemoryStream stream = new MemoryStream())
                {
                    Formatter.Serialize(stream, src);
                    stream.Position = 0;
                    return Formatter.Deserialize(stream);
                }
            }
    深拷贝、浅拷贝(引用类型)

    正则表达式

     正则表达式是用来进行文本,字符串进行处理的技术,是语言无关的。

    元字符

    表1.常用的元字符
    代码说明
    . 匹配除换行符以外的任意字符
    w 匹配字母或数字或下划线或汉字
    s 匹配任意的空白符
    d 匹配数字
    b 匹配单词的开始或结束
    ^ 匹配字符串的开始
    $ 匹配字符串的结束

     

    表2.常用的限定符
    代码/语法说明
    * 重复零次或更多次
    + 重复一次或更多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次

     

    表3.常用的反义代码
    代码/语法说明
    W 匹配任意不是字母,数字,下划线,汉字的字符
    S 匹配任意不是空白符的字符
    D 匹配任意非数字的字符
    B 匹配不是单词开头或结束的位置
    [^x] 匹配除了x以外的任意字符
    [^aeiou] 匹配除了aeiou这几个字母以外的任意字符

     

    表4.常用分组语法
    分类代码/语法说明
    捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
    (?<name>exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成 (?'name'exp)
    (?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
    零宽断言 (?=exp) 匹配exp前面的位置
    (?<=exp) 匹配exp后面的位置
    (?!exp) 匹配后面跟的不是exp的位置
    (?<!exp) 匹配前面不是exp的位置
    注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅 读

     

    贪婪与懒惰

    •贪婪:.+。(默认为贪婪模式,尽可能的多匹配。)
    •非贪婪:.+?。(尽可能的少匹配,(1个。))

    当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的 字符。以这个表达式为例:a.*b,它将会匹配最长的以 a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。

    有时,我们更需要懒惰匹配,也就是匹配尽可能少的 字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提 下使用最少的重复。现在看看懒惰版的例子吧:

    a.*?b匹配最短的,以a开始,以b结 束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。

    为什么第一个匹配是aab(第一到第三个字符)而不是ab(第二到第三个字符)?简单地说,因为正则表达式有另 一条规则,比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权——The match that begins earliest wins。

    表5.懒惰限定符
    代码/语法说明
    *? 重复任意次,但尽可能少重复
    +? 重复1次或更多次,但尽可能少重复
    ?? 重复0次或1次,但尽可能少重复
    {n,m}? 重复n到m次,但尽可能少重复
    {n,}? 重复n次以上,但尽可能少重复

    处理选项

    在C#中,你可以使用Regex(String, RegexOptions)构造函数来设置正则表达式的处理选项。 如:Regex regex = new Regex(@"baw{6}b", RegexOptions.IgnoreCase);

    上面介绍了几个选项如忽略大小写,处理多行等,这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项:

    表6.常用的处理选项
    名称说明
    IgnoreCase(忽略大小写) 匹配时不区分大小写。
    Multiline(多行模式) 更改^和$的 含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的 精确含意是:匹配n之前的位置以及字符串结束前的位置.)
    Singleline(单行模式) 更改.的含义,使它与每一个字符匹配(包括换行 符n)。
    IgnorePatternWhitespace(忽略空白) 忽略表达式中的非转义空白并启用由#标记的注释。
    ExplicitCapture(显式捕获) 仅捕获已被显式命名的组。

    一个经常被问到的问题是:是不是只能同时使用多行模式和单行模式中的一种?答案是:不是。这两个选项之间没有任何关系,除了它们的名字比较 相似(以至于让人感到疑惑)以外。

     

    表7.尚未详细讨论的语法
    代码/语法说明
    a 报警字符(打印它的效果是电脑嘀一声)
    b 通常是单词分界位置,但如果在字符类里使用代表退格
    t 制表符,Tab
    r 回车
    v 竖向制表符
    f 换页符
    n 换行符
    e Escape
    0nn ASCII代码中八进制代码为nn的字符
    xnn ASCII代码中十六进制代码为nn的字符
    unnnn Unicode代码中十六进制代码为nnnn的字符
    cN ASCII控制字符。比如cC代表Ctrl+C
    A 字符串开头(类似^,但不受处理多行选项的影响)
    Z 字符串结尾或行尾(不受处理多行选项的影响)
    z 字符串结尾(类似$,但不受处理多行选项的影响)
    G 当前搜索的开头
    p{name} Unicode中命名为name的字符类,例如p{IsGreek}
    (?>exp) 贪婪子表达式
    (?<x>-<y>exp) 平衡组
    (?im-nsx:exp) 在子表达式exp中改变处理选项
    (?im-nsx) 为表达式后面的部分改变处理选项
    (?(exp)yes|no) 把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为 此组的表达式;否则使用no
    (?(exp)yes) 同上,只是使用空表达式作为no
    (?(name)yes|no) 如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用 no
    (?(name)yes) 同上,只是使用空表达式作为no

     

    Delegate

    用委托可以指向任意的函数,哪怕之前没有定义------通过匿名方法去实现(只需要用一次的方法 ),写在主函数里,如DelString del=delegate(string str){return ""“+str+""";};

    线程就是一个委托

    Event

    事件:事件和属性差不多,自动定义了一个私有的委托,在事件中自动封装了Add(给私有委托注册方法)和Remove方法,事件是一个对象,委托是数据类型,事件调用Add,Remove方法进行注册或删除私有委托所指定的方法.

    委托和事件的区别(常考)

    1:委托和事件没有可比性,因为委托是数据类型,事件是对象(可以理解为对委托变量的封装。),下面说的是委托的对象(用委托方式实现的事件)和(标准的event方式实现)事件的区别。事件的内部是用委托实现的。(举例子:三种实现事件方式的区别(直接用委托实现、用私有委托+公有方法模拟事件,直接用event事件实现))
    2:因为对于事件来讲,外部只能“注册自己+=、注销自己-=”,外界不可以注销其他的注册者,外界不可以主动触发事件,因此如果用Delegate就没法进行上面的控制,因此诞生了事件这种语法。add、remove。
    3:事件是用来阉割委托实例的。事件只能add、remove自己,不能赋值。事件只能+=、-=,不能=、不能外部触发事件。
     
     
    程序集
    每个程序集都有自己的名称、版本等信息。这些信息可以通过AssemblyInfo.cs文件来自己定义,包含:
    1:类型元数据(描述在代码中定义的每一类型和成员,二进制形式)
    2:程序集元数据(程序集清单、版本号、名称等)
    3:IL代码(这些都被装在exe或dll中)
    4:资源文件。

    AppDomain.CurrentDomain.GetAssemblies()

    反射

    1:反射就是动态获取程序集的元数据(提供程序集的类型信息)来操作类型的.
    2:Type类是实现反射的一个重要的类,通过它可以获取类中的所有信息包括方法、属性等。可以动态调用类的属性、方法。 Type是对类的描述。
    3:反射就是直接通过.dll来创建对象,调用成员。
     
    //命名空间
    string nameSpace =System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;  
    
     //文件名
    string className = Path.GetFileNameWithoutExtension(path);
    
    //类的全名称
    string fullName = nameSpace+"."+className;
    
    System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(fullName,true) ;
    反射获取实例
     
    Type类的使用:
    •通过类获得Type:Type t = typeof(Person)
    •通过对象获得类的Type:Type t = p.GetType()
    •“c:abc.dll”
    •Assembly asm=Assembly.LoadFile(“c:abc.dll”);
    •调用Assembly的GetExportedTypes方法可以得到Assembly中定义的所有的public类型。
    •调用Assembly的GetTypes()方法可以得到Assembly中定义的所有的类型。
    •调用Assembly的GetType(name)方法可以得到Assembly中定义的全名为name的类型信息。
    •插件:扩展主程序功能的dll.
     
    Type类的方法:(在编写调用插件的程序时,需要做一系列验证。)
    •bool IsAssignableFrom(Type c):(直译:是否可以从c赋值)判断当前的类型的变量是不是可以接受c类型变量的赋值。typeof(IPlugin).IsAssignableFrom(t) 
    •bool IsInstanceOfType(object o):判断对象o是否是当前类的实例(当前类可以是o的类、父类、接口)
    •bool IsSubclassOf(Type c):判断当前类是否是类c的子类。类的事,没有接口的事。
    •IsAbstract,判断是否为抽象的,含接口
     
    动态创建对象:
    Activator.CreateInstance(Type t)会动态调用类的无参构造函数创建一个对象,如果类没有无参构造函数就会报错。
     
    动态调用成员:
    1:MemberInfo类  抽象类,有很多子类,下面讲的类都继承自它,获取程序集成员的相关信息(类型、方法、事件、字段和属性)
    2:PropertyInfo  获取属性
        •主要成员:CanRead、CanWrite、PropertyType属性类型;
                        SetValue、GetValue:读取值,设置值,第一个参数是实例对象,因为set、get要针对具体实例,最后一个参数null。pInfo.SetValue(p1, 30, null)
    3:MethodInfo  获取方法
        •MethodInfo都是和具体对象相关的,所以需要第一个参数指定要执行的对象。
    4:FieldInfo  获取字段
    5:EventInfo  获取事件
    “生成此程序的程序集比加载的运行时新”,因为用Vs2008开发的主程序,但插件用的是Vs2010开发的。新建的时候选择.net3.5Framework就可以了。
    
     public void ShutDown(string second)
            {
                Process process = new Process();
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.CreateNoWindow = true;
                process.Start();
                process.StandardInput.WriteLine("shutdown -s -f -t " + second);
                //process.StandardInput.WriteLine("dir c:");
                process.StandardInput.WriteLine("exit");
    
    
                process.Close();
            }
    
    //通过接口定义 插件怎么去实现 
    public interface IPlugin
        {
            string PluginName
            {
                get;
            }
            string Execute(string param);
        }
    //窗体加载
    void LoadMenu() {
                string path = AppDomain.CurrentDomain.BaseDirectory;
                path = Path.Combine(path, "Plugin");
                string[] plugins = Directory.GetFiles(path,"*.dll");
                foreach (string plugin in plugins)
                {
                    Assembly ass = Assembly.LoadFile(plugin);
                    foreach (Type t in ass.GetExportedTypes())
                    {
                        //typeof(IPlugin).IsAssignableFrom(t)判断t这种类型是否实现了接口
                        if (typeof(IPlugin).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract)
                        {
                            IPlugin ip = Activator.CreateInstance(t) as IPlugin;
                            ToolStripItem tsi = TSMITools.DropDownItems.Add(ip.PluginName);
                            tsi.Tag = ip;
                            tsi.Click += new EventHandler(tsi_Click);
                        }
                    }
                }
            }
    
            void tsi_Click(object sender, EventArgs e)
            {
                ToolStripItem tsi = sender as ToolStripItem;
                IPlugin ip = tsi.Tag as IPlugin;
                if (ip != null) 
                {
                   string r = ip.Execute(textBox1.Text);
                   if (!string.IsNullOrEmpty(r))
                   {
                       MessageBox.Show(r);
                   }
                }
            }
    
    
    //关机插件
    public class Cmd:IPlugin
        {
            public string PluginName
            {
                get 
                {
                    return "关机插件";
                }
            }
    
            public string Execute(string param)
            {
                ShutDown(param);
                return "";
            }
    
            public void ShutDown(string second)
            {
                Process process = new Process();
                process.StartInfo.FileName = "cmd.exe";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardInput = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;
                process.StartInfo.CreateNoWindow = true;
                process.Start();
                process.StandardInput.WriteLine("shutdown -s -f -t " + second);
                //process.StandardInput.WriteLine("dir c:");
                process.StandardInput.WriteLine("exit");
    
                process.Close();
            }
        }
    
    
    //字典插件
    public class Dic:IPlugin
        {
            public string PluginName
            {
                get { return "字典插件"; }
            }
    
            public string Execute(string param)
            {
                return Translate(param);
            }
       
            public string Translate(string key)
            {
                Dictionary<string, string> dic = new Dictionary<string, string>();
                dic.Add("english", "英语");
                dic.Add("chinese", "中文");
                dic.Add("eat", "");
                dic.Add("dog", "");
                if (dic.ContainsKey(key))
                {
                    return dic[key];
                }
                else 
                {
                    return null;
                }
            }
        }
    插件
    Type type = typeof(Person);
    MethodInfo method = type.GetMethod("SayHi", BindingFlags.NonPublic | BindingFlags.Instance);
    
    object obj = Activator.CreateInstance(type);
    method.Invoke(obj, null);
    
     public class Person
        {
            private void SayHi()
            {
                Console.WriteLine("hi!");
            }
        }
    通过反射访问私有成员

    隐式类型(类型推断)

    var关键字(在编译时已经能确定变量的类型了。并不是弱类型。根据后面的值自动推断类型,编译时把推断的类型替换掉var,只是方便程序员使用而已)
    •var k = "C Sharp";//string
    •var x;//错误
    •var y = null;//错误
    •var z = { 1, 2, 3 };//错误  var z=new[] {1,2,3};//正确。
    注意:不能作为类成员的类型、不能用作方法的参数,返回值。(只能用作局部变量的类型推断)

    可以使用new关键字调用匿名初始化器创建一个匿名类型的对象。匿名类型直接继承自System. Object。 

    var p2 = new { Id = 2, Name = "XieQing", Age = 25 };
    •var intArray = new[] { 2, 3, 5, 6 }; 
     
    扩展方法-Linq中用的很多。
    声明扩展方法的步骤:类必须是static,方法是static,第一个参数是被扩展的对象,前面标注this(this 数据类型 参数名)。
     
    Xml
    1.严格区分大小写
    2.有且只能有一个根节点
    3.有开始标签必须有结束标签
    4.属性必须使用双引号
    5.没有预定义标签与html不一样
    6.文档声明:<?xml version="1.0" encoding="utf-8"?>
    7.注释:<!-- -->
    8.CDATA区:即原意文本-<![CDATA[…]]>
    9.注意编码问题,文本文件实际编码要与文档声明中的编码一致。

    <![CDATA[  文本 ]]>:<![CDATA[  这里的文字将被解析为纯文本,即便有  <  >的标签也不会被解析为xml标签。  ]]>

    读写XML有很多技术:
    1.Dom[XmlDocument、XDocument](文档对象模型,将整个xml加载到内存中,然后操作)
    •XmlDocument→.net2.0
    •XDocument→net3.x(Linq to Xml)
    2.Sax(Simple API for XML,事件驱动,.net中使用XmlReader(XmlTextReader)、XmlWriter(XmlTextWriter)来替代)等,还有高级的读写技术
    3.XmlSerializer(xml序列化,需要先定义类)
    4.Linq To XML(System.Xml.Linq),用到的就是Xdocument,Xelement等等
     
    XmlSerializer要求对每种不同的文件都定义一套类,很麻烦,而Linq To XML则不需要单独创建类,当然更底层一些,代码比XmlSerializer多,灵活性更高。System.Xml下的类是2.0及之前操作xml推荐的,现在很多人也仍然在用这个namespace下的类,这个namespace下的类和Linq To XML非常相似,因此不用单独学。
     
    Schema、DTD:在App.Config中“转到定义”会看到文件的定义约束文件,DTD约束能有哪些属性、能有哪些元素
     
    RSS

    RSS是站点用来和其他站点之间共享内容的简易方式( 也叫聚合内容)。RSS使用XML作为彼此共享内容的标准方式。它代表了Really Simple Syndication(或RDF Site Summary,RDF站点摘要)。 它能让别人很容易的发现你已经更新了你的站点, 并让人们很容易的追踪他们阅读的 所有weblogs。

    http://tech.163.com/special/000915SN/simplerss.html

  • 相关阅读:
    Qt 的插件制作遇到的问题
    Qt实现原生Flow实现不了的Item错误排列效果,类似淘宝商品展示
    通过pro文件使Qt的build目录更清爽
    No rule to make target
    Qtcreator中printf()/fprintf()不显示问题处理方法
    QtCreator集成的MSVC套件有问题
    启动程序失败,路径或者权限错误
    图数据库 Nebula Graph 的数据模型和系统架构设计
    NLP(十六)轻松上手文本分类
    NLP(十五)让模型来告诉你文本中的时间
  • 原文地址:https://www.cnblogs.com/CrabMan/p/5166462.html
Copyright © 2020-2023  润新知