• C#基础回顾(三)—索引器、委托、反射


    一.前言


                                                                                          ------人生路蜿蜒曲折,独自闯荡

    二.索引器

    (1)定义:

    索引器是一种特殊的类成员,它能够让对象以类似数组的形式来存取,使程序看起来更为直观,更容易编写。

    定义形式如下:

    [修饰符] 数据类型 this[索引类型 index]

    {

    get{//获得属性的代码}

    set{//设置属性的代码}

    }

    其中,修饰符包括:public,protected,private,internal,new,virtual,sealed,override, abstract,extern.

    (2)实现Demo:

    【单参数索引器】

    static void Main(string[] args)

    {

    //一般索引器(参数为int类型)

    Console.WriteLine("--------------int类型作为下标对索引器进行存储------------------");

    var worker = new IndexerWork();

    worker[0] = "liupeng";

    worker[1] = "zhangyonghe";

    Console.WriteLine(string.Format("一号员工的名字为:{0}", worker[0]));

    Console.WriteLine(string.Format("二号员工的名字为:{0}", worker[1]));

    Console.WriteLine("--------------string类型作为下标对索引器进行存储---------------");

    //索引器(参数为string类型)

    var ht = new IndexerWork();

    ht["AA"] = "liupeng";

    ht["BB"] = "zhangyonghe";

    Console.WriteLine(string.Format("一号员工的名字为:{0}", ht["AA"]));

    Console.WriteLine(string.Format("二号员工的名字为:{0}", ht["BB"]));

    Console.ReadKey();

    }

    public class IndexerWork

    {

    public string[] Worker = new string[10];

    private readonly Hashtable Ht = new Hashtable();

    public string this[int index]

    {

    get { return Worker[index]; }

    set { Worker[index] = value; }

    }

    public string this[string index]

    {

    get { return Ht[index].ToString(); }

    set { Ht.Add(index, value); }

    }

    }

    运行结果为:

    【多参数索引器】        

       //多参数索引器          

     var moreIndexer = new IndexerWork();          

    moreIndexer[1, "AA"] = "I am work in BaiDu!";        

     moreIndexer[2, "BB"] = "I am work in LeTv";        

      Console.WriteLine(string.Format("一员工的公司为:{0}", moreIndexer[1, "AA"]));        

      Console.WriteLine(string.Format("二员工的公司为:{0}", moreIndexer[2, "BB"]));      

    public class IndexerWork        {        

      private readonly List_stuList = new List();

      public string this[int index, string name]

    {

    get

    {

    var list = _stuList.Find(x => x.StuNo == index && x.StuName == name);

    return list.ClassName;

    }

    set

    {

    _stuList.Add(new StudentInfo()

    {

    StuNo = index,

    StuName = name,

    ClassName = value

    }

    );

    }

    }

    }

    运行结果为:

    三.委托

    (1)定义:

    delegate 是表示对具有特定参数列表和返回类型的方法的引用的类型。在实例化委托时,你可以将其实例与任何具有兼容签名和返回类型的方法相关联—— MSDN

    就我个人理解而言,委托可以看做一个函数的指针,可以把一个函数作为一个参数带入到另一个函数中;也就是函数可以把自己委托给声明的委托对象,进行一系列的操作。

     

    定义形式如下:

    public delegate int PerformCalculation(int x, int y);

    【1】简单委托

    定义DeletegateDemo,并实现两个方法GetStatus和GetSimpleSign,分别接受一个int类型的参数:

    public class DeletegateDemo

    {

    public void GetStatus(int num)

    {

    if (num > 0)

    {

    Console.WriteLine("大于0");

    }

    else if (num < 0)

    {

    Console.WriteLine("小于0");

    }

    }

    public static void GetSimpleSign(int num)

    {

    if (num > 0)

    {

    Console.WriteLine("+");

    }

    else if (num < 0)

    {

    Console.WriteLine("—");

    }

    }

    }

    可利用委托,我们可以讲两个方法作为参数传递给委托对象,进行操作。首先在Main函数外面声明委托对象

    public delegate void GetMySignDeletegate(int num);

    然后在Main函数里面我们可以这样实现:

    static void Main(string[] args)

    {

    var signObj = new DeletegateDemo();

    var mySignDelegateOne = new GetMySignDeletegate(signObj.GetStatus);

    var mySignDelegateTwo = new GetMySignDeletegate(DeletegateDemo.GetSimpleSign);

    mySignDelegateOne(5);

    mySignDelegateTwo(-3);

    Console.ReadKey();

    }

    运行结果为:

    【2】多播委托

    委托可以包含多个方法,这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名必须返回void,否则就只能得到委托调用的最后一个方法的结果。

    多播委托可以使用运算符“+”和“+=”添加方法,也可以使用“-”和“-=”从委托中删除方法调用。

    因此我们可以在Main函数中通过“+”和“—“来进行委托的注入和去除。

    static void Main(string[] args)

    {

    var signObj = new DeletegateDemo();

    var mySignDelegateOne = new GetMySignDeletegate(signObj.GetStatus);

    var mySignDelegateTwo = new GetMySignDeletegate(DeletegateDemo.GetSimpleSign);

    GetMySignDeletegate myDeletegate = null;

    myDeletegate += mySignDelegateOne;

    myDeletegate += mySignDelegateTwo;

    myDeletegate(4);

    }

    运行结果为:

    三.反射

    (1)定义

    Reflection,中文翻译为反射。这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,例如:

    Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。

    Type类可以获得对象的类型信息,此信息包含对象的所有要素:方法、构造器、属性等等,通过Type类可以得到这些要素的信息,并且调用之。

    MethodInfo包含方法的信息,通过这个类可以得到方法的名称、参数、返回值等,并且可以调用之。

    诸如此类,还有FieldInfo、EventInfo等等,这些类都包含在System.Reflection命名空间下。

    (2)实现Demo

    【1】Type类于获取类型信息

    定义class,我们可以在Main函数中获取定义类型的相关信息:

    static void Main(string[] args)

    {

    var reflctionObject=new MyReflection();

    var type = reflctionObject.GetType();

    Console.WriteLine("类型名:" + type.Name);

    Console.WriteLine("类全名:" + type.FullName);

    Console.WriteLine("命名空间名:" + type.Namespace);

    Console.WriteLine("程序集名:" + type.Assembly);

    Console.WriteLine("模块名:" + type.Module);

    Console.WriteLine("基类名:" + type.BaseType);

    Console.WriteLine("是否类:" + type.IsClass);

    Console.WriteLine("类的公共成员:");

    var memberInfos = type.GetMembers();//得到所有公共成员

    foreach (var item in memberInfos)

    {

    Console.WriteLine("{0}:{1}", item.MemberType, item);

    }

    Console.ReadKey();

    }

    //定义class

    public class  MyReflection

    {

    public string m = null;

    public string Name { get; set; }

    public void ShowMessage()

    {

    Console.WriteLine("My name is liupeng!");

    }

    }

    运行结果:

     

    【2】 获取程序集元数据

    static void Main(string[] args)

    {

    //获取当前执行代码的程序集

    Assembly assem = Assembly.GetExecutingAssembly();

    Console.WriteLine("程序集全名:"+assem.FullName);

    Console.WriteLine("程序集的版本:"+assem.GetName().Version);

    Console.WriteLine("程序集初始位置:"+assem.CodeBase);

    Console.WriteLine("程序集位置:"+assem.Location);

    Console.WriteLine("程序集入口:"+assem.EntryPoint);

    Type[] types = assem.GetTypes();

    Console.WriteLine("程序集下包含的类型:");

    foreach (var item in types)

    {

    Console.WriteLine("类:"+item.Name);

    }

    }

    运行结果:

    【3】 动态加载类型

    早绑定是在编译时绑定对象类型,而晚绑定是在运行时才绑定对象的类型。利用反射可以实现晚绑定,即动态加载类型,并调用他们的方法

    static void Main(string[] args)

    {

    //动态创建类型

    //获取当前执行代码的程序集

    Assembly assem = Assembly.GetExecutingAssembly();

    Console.WriteLine("Assembly Full Name:");

    Console.WriteLine(assem.FullName);

    // The AssemblyName type can be used to parse the full name.

    AssemblyName assemName = assem.GetName();

    Console.WriteLine("\\nName: {0}", assemName.Name);

    Console.WriteLine("Version: {0}.{1}",

    assemName.Version.Major, assemName.Version.Minor);

    Console.WriteLine("\\nAssembly CodeBase:");

    Console.WriteLine(assem.CodeBase);

    // 从程序集中创建一个Example实例并且用object类型的引用o指向它,同时调用一个输入参数的构造函数

    Object o = assem.CreateInstance("Reflection.Example", false,

    BindingFlags.ExactBinding,

    null, new Object[] { 2 }, null, null);

    //构造Example类的一个晚绑定的方法SampleMethod

    MethodInfo m = assem.GetType("Reflection.Example").GetMethod("SampleMethod");

    //调用刚才实例化好的Example对象o中的SampleMethod方法,传入的参数为42

    Object ret = m.Invoke(o, new Object[] { 42 });

    Console.WriteLine("SampleMethod returned {0}.", ret);

    Console.WriteLine("\\nAssembly entry point:");

    Console.WriteLine(assem.EntryPoint);

    Console.ReadKey();

    }

    public class Example

    {

    private int factor;

    public Example(int f)

    {

    factor = f;

    }

    public int SampleMethod(int x)

    {

    Console.WriteLine("\\nExample.SampleMethod({0}) executes.", x);

    return x * factor;

    }

    }

    运行结果为:

     

    四.反射的运用

    (1)使用反射通过读取配置文件来动态的创建相关类的对象

    //主函数

    public static void Main()

    {

    #region 同程序集下

    System.Type type = System.Type.GetType(ConfigurationManager.AppSettings["LogType"].ToString());

    ILog log = (ILog)Activator.CreateInstance(type);

    log.Write(new Exception("异常测试"));

    #endregion

    #region 不同程序集

    string assemblyPath = Path.Combine(Environment.CurrentDirectory, "LogClassLibrary.dll");

    Assembly a = Assembly.LoadFrom(assemblyPath);

    Type type = a.GetType(ConfigurationManager.AppSettings["LogType"].ToString());

    LogClassLibrary.ILog log = (LogClassLibrary.ILog)type.InvokeMember(null,BindingFlags.CreateInstance,null,null,null);

    log.Write(new Exception("异常测试"));

    #endregion

    }

    //app.config

    //方法实现

    public class TextFileLog : ILog

    {

    public bool Write(string message)

    {

    string fileDir = ConfigurationManager.AppSettings["LogTarget"].ToString();

    using (StreamWriter w = File.AppendText(fileDir))

    {

    // w.Write(" Log Entry : ");

    w.WriteLine("发生时间{0}", DateTime.Now.ToLocalTime().ToString());

    w.WriteLine("日志内容为:{0}", message);

    w.WriteLine("-------------------------------");

    // Update the underlying file.

    w.Flush();

    w.Close();

    }

    return true;

    }

    public bool Write(Exception ex)

    {

    Write(ex.Message);

    return true;

    }

    }

    运行以后在C盘目录下,可以看到日志记录:

    (2)插件编程技术

    插件是指遵循一定的接口规范、可以动态加载和运行的程序模块。从上面的例子可以看出,通过反射可以非常方便的动态加载程序集。因此,利用反射的动态加载代码能力,可以很容易的实现插件。

    插件编程的要点是使用接口来定义插件的功能特征。插件的宿主程序通过接口来确认、装载和执行插件的功能,实现插件功能的所有类都必须实现定义插件的接口。

    【1】宿主加载插件

    public class Host : IHost    {      

     private Listplugins = new List();      

    #region IHost 成员        

    public ListPlugins

    {

    get { return plugins; }

    }

    public int LoadPlugins(string path)

    {

    string[] assemblyFiles = Directory.GetFiles(path, "*.dll");

    foreach (var file in assemblyFiles)

    {

    Assembly assembly = Assembly.LoadFrom(file);

    foreach (var type in assembly.GetExportedTypes())

    {

    if (type.IsClass && typeof(ILog).IsAssignableFrom(type))

    {

    ILog plugin = Activator.CreateInstance(type) as ILog;

    plugins.Add(plugin);

    }

    }

    }

    return plugins.Count;

    }

    public ILog GetLog(string name)

    {

    foreach (var item in plugins)

    {

    if (item.GetType().ToString()==name)

    {

    return item;

    }

    }

    return null;

    }

    #endregion

    【2】接口定义    public interface IHost    {        ListPlugins { get; }

    int LoadPlugins(string path);

    ILog GetLog(string name);

    }

    【3】主函数调用

    static void Main(string[] args)

    {

    Host.Host host = new Host.Host();

    host.LoadPlugins(".");

    InterfaceLayer.ILog log = host.GetLog(ConfigurationManager.AppSettings["LogType"].ToString());

    log.Write(new Exception("异常测试"));

    }

  • 相关阅读:
    some tips
    ORA00847: MEMORY_TARGET/MEMORY_MAX_TARGET and LOCK_SGA cannot be set together
    Chapter 01Overview of Oracle 9i Database Perfomrmance Tuning
    Chapter 02Diagnostic and Tuning Tools
    变量与常用符号
    Chapter 18Tuning the Operating System
    标准输入输出
    Trace files
    DBADeveloped Tools
    Chapter 03Database Configuration and IO Issues
  • 原文地址:https://www.cnblogs.com/liupeng61624/p/5135341.html
Copyright © 2020-2023  润新知