一.前言

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

二.索引器

(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("异常测试"));

}

C#基础回顾(三)—索引器、委托、反射的更多相关文章

  1. .NET基础知识之七——索引器

           索引器是什么?有什么作用?索引器允许类的实例以访问数组的形式来访问对象里面的属性.如我们经常可以看到类似于dr["name"]="test",或者 ...

  2. java基础回顾(三)——HashMap与HashTable

    public class Hashtable extends Dictionary implements Map, Cloneable, java.io.Serializable public cla ...

  3. 《Inside C#》笔记(六) 属性、数组、索引器

    一 属性 a) 属性可用于隐藏类的内部成员,对外提供可控的存取接口.属性相当于有些语言的getter.setter方法,只是使用起来更加方便一点,而且查看对应的IL码可以看到,属性的本质也确实是方法. ...

  4. 第一篇 .NET高级技术之索引器

    基础知识补充 索引 器 没有名字 ,索引器的内部本质 (ILSpy的IL模式下看)类型 this[参数]{get;set;} 可以是只读或者只写(在get或者set前加上private) 字符串是只读 ...

  5. Javascript基础回顾 之(三) 面向对象

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  6. C#基础加强(1)之索引器

    索引器 介绍 索引器,初学者可能听起来有些陌生,但其实我们经常会用到它,例如: // 字符串的索引器 string str = "hello world"; ]; // 获取到字符 ...

  7. C# 基础之索引器

    当一个类有数组成员时,索引器将大大简化对类中数组成员的访问 索引器类似于属性有get与set访问器 列如: 使用: 总结:从以上代码可以看出索引器也是对私有字段进行访问的方式,但此时的私有字段是数组类 ...

  8. C#基础--索引器

    classProgram { staticvoidMain(string[] args) { man mm =new man(); mm[0]="jingya"; mm[1]=&q ...

  9. 【Unity|C#】基础篇(7)——属性(Property)/ 索引器(Indexer)

    [学习资料] <C#图解教程>(第6章):https://www.cnblogs.com/moonache/p/7687551.html 电子书下载:https://pan.baidu.c ...

随机推荐

  1. javascript:逆波兰式表示法计算表达式结果

    逆波兰式表示法,是由栈做基础的表达式,举个例子: 5 1 2 + 4 * + 3 -  等价于   5 + ((1 + 2) * 4) - 3 原理:依次将5 1 2 压入栈中, 这时遇到了运算符 + ...

  2. DataTable 转换成 Json的3种方法

    在web开发中,我们可能会有这样的需求,为了便于前台的JS的处理,我们需要将查询出的数据源格式比如:List<T>.DataTable转换为Json格式.特别在使用Extjs框架的时候,A ...

  3. 从Vue.js窥探前端行业

    近年来前端开发趋势 1.旧浏览器逐渐淘汰,移动端需求增加: 旧浏览器主要指的是IE6-IE8,它是不支持ES5特性的:IE9+.chrome.sarafi.firefox对ES5是完全支持的,移动端大 ...

  4. Eclipse出现"Running Android Lint has encountered a problem"解决方案

    安装eclipse for android 时候的错误记录,转载自:http://blog.csdn.net/chenyufeng1991/article/details/47442555 (1)打开 ...

  5. 【QQ红包】手机发抢不到的口令红包

    这方法95%的人都抢不了 在QQ输入框输入一个表情,例如:阴险那个表情 将表情剪切到口令红包的口令里 这时候口令里的那个表情表情变成了符号 将符号删去一格,然后全选.复制 然后返回到QQ输入框粘贴 然 ...

  6. SQL Server的AlwaysOn错误19456和41158

    SQL Server的AlwaysOn错误19456和41158 最近在公司搞异地数据库容灾,使用AlwaysOn的异地节点进行数据同步,在搭建的过程中遇到了一些问题 软件版本 SQL Server2 ...

  7. CSS垂直居中总结

    工作中遇到垂直居中问题,特此总结了一下几种方式与大家分享.本文讨论的垂直居中仅支持IE8+ 1.使用绝对定位垂直居中 <div class="container"> & ...

  8. 我认为JS还可以改进的点

    曾经我一度在寻找JS的替代语言,尝试过CoffeeScript/TypeScript/Dart(都是浅尝).不为什么原因,而是当你写的越多的JS,越觉得JS很多时候显得很操蛋.好在ES2015和Bab ...

  9. 深入解析js异步编程利器Generator

    我们在编写Nodejs程序时,经常会用到回调函数,在一个操作执行完成之后对返回的数据进行处理,我简单的理解它为异步编程. 如果操作很多,那么回调的嵌套就会必不可少,那么如果操作非常多,那么回调的嵌套就 ...

  10. [Mahout] 完整部署过程

    概述        Mahout底层依赖Hadoop,部署Mahout过程中最困难的就是Hadoop的部署      本文假设用户本身没有进行Hadoop的部署,记述部署Mahout的过程       ...