.net编程中的一些技巧(二)

来源:互联网 发布:qt串口接收数据 编辑:程序博客网 时间:2024/05/16 07:06
Programming With Reflection
Reflection的主要用途是执行时期提供类型信息。
在.NET FRAMEWORK中,Reflection通过Type对象来操作。

其中分成2部分:
一是提供Type本身的信息,比如public、sealed等等,直接通过IsPublic等属性获得;
二是提供Type内成员信息,返回值为MemberInfo或其派生类的实例,比如GetConstructor(s)返回ConstructorInfo对象或数组、GetField(s)返回FieldInfo对象或数组。

关于Type类的详细信息请参看
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpref/html/frlrfsystemtypememberstopic.asp

Dynamic Invoke

Reflection允许设计人员动态调用函数。可以通过MethodInfo对象的Invoke方法调用,也可以直接通过Type的InvokeMember来调用。


namespace DesignPattern
{
/// <summary>
/// reflectiontest 的摘要说明。
/// </summary>
public class reflectiontest : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
MyData md=new MyData(10);
object[] o=new object[]{1};
o[0]=5;

Type t=typeof(MyData);//获取MyData的Type信息
MethodInfo mi=t.GetMethod("Zero");
mi.Invoke(md,null);//通过MethodInfo对象的Invoke方法调用md的Zero
Response.Write(md.getnum());
t.InvokeMember("setnum", BindingFlags.InvokeMethod ,null,md,o);//通过Type的InvokeMember调用md的setnum
Response.Write(t.InvokeMember("getnum",BindingFlags.InvokeMethod,null,md,null));
}
#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}

//一个简单的类,有一个int的私有成员,公共方法有归0,赋值以及获取。
public class MyData
{
private int i;
public MyData(int a)
{
i=a;
}
public void Zero()
{
i=0;
}
public void setnum(int a)
{
i=a;
}
public int getnum()
{
return i;
}
}
}

写Reflection的时候别忘了using System.Reflection;

Collection

Collection是指聚集一群元素的容器,概念由数组延伸而来。

1、IEnumerable接口。实现该接口的对象可使用foreach。IEnumerable接口只预定义一个函数GetEnumerator,返回一个IEnumerator对象实例。

以下是代码实例:


public class MyEnumerator:IEnumerator
{
private int _index;
private string[] _list;
public MyEnumerator(string[] list)
{
_index=-1;
_list=list;
}
public void Reset()
{
_index=-1;
}
public object Current
{
get
{
return _list[_index];
}
}
public bool MoveNext()
{
_index++;
if(_index>=_list.Length)
{
_index=_list.Length-1;
return false;
}
return true;
}
}
public class MyEnumerable:IEnumerable
{
private string[] _list;
public MyEnumerable()
{
_list=new string[3]{"1","2","3"};
}
public IEnumerator GetEnumerator()
{
return new MyEnumerator(_list);
}
}

有了以上实现了IEnumerator和IEnumerable接口的类后,通过以下代码可以输出123

MyEnumerable me=new MyEnumerable();
foreach(string s in me)Response.Write(s);

2、ICollection接口是IEnumerable的加强型接口

public interface ICollection:IEnumerable
{
int Count{get;}
object SyncRoot{get;}
bool IsSynchronized{get;}
void CopyTo(Array array,int index);
}

以下代码的类实现了ICollection接口

public class MyCollection:ICollection
{
private string[] _list;
private object _root;
public MyCollection()
{
_list=new string[3]{"1","2","3"};
}
public bool IsSynchronized
{
get
{
return true;
}
}
public int Count
{
get
{
return _list.Length;
}
}
public void CopyTo(Array array, int index)
{
_list.CopyTo(array,index);
}
public object SyncRoot
{
get
{
return _root;
}
}
public IEnumerator GetEnumerator()
{
return _list.GetEnumerator();
}
}

3、IList接口提供了修改Collection内部元素的能力。事实上它是IEnumerable和ICollection接口的综合体。
其原型如下

public interface IList:ICollection,IEnumerable
{
object this[int index]{get;set;}
bool IsReadOnly{get;}
bool IsFixedSize{get;}
int Add(object value);
bool Contains(object value);
void Clear();
int IndexOf(object value);
void Insert(int index,object value);
void Remove(object value);
void RemoveAt(int index);
}
下面是一个实现了IList接口的类
public class MyList:IList
{
private ArrayList _list;
public MyList()
{
_list=new ArrayList();
}
#region IList 成员
public bool IsReadOnly
{
get
{
return false;
}
}
public object this[int index]
{
get
{
return _list[index];
}
set
{
_list[index]=value;
}
}
public void RemoveAt(int index)
{
_list.RemoveAt(index);
}
public void Insert(int index, object value)
{
_list.Insert(index,value);
}
public void Remove(object value)
{
_list.Remove(value);
}
public bool Contains(object value)
{
return _list.Contains(value);
}
public void Clear()
{
_list.Clear();
}
public int IndexOf(object value)
{
return _list.IndexOf(value);
}
public int Add(object value)
{
return _list.Add(value);
}
public bool IsFixedSize
{
get
{
return false;
}
}
#endregion
#region ICollection 成员
public bool IsSynchronized
{
get
{
return _list.IsSynchronized;
}
}
public int Count
{
get
{
return _list.Count;
}
}
public void CopyTo(Array array, int index)
{
_list.CopyTo(array,index);
}
public object SyncRoot
{
get
{
return _list.SyncRoot;
}
}
#endregion
#region IEnumerable 成员
public IEnumerator GetEnumerator()
{
return _list.GetEnumerator();
}
#endregion
}

4、前面几个接口都使用object作为Collection中的元素类型,这样所有对象都可以放入Collection中,但是,这种设计过于松散,容易产生混用,有时候需要一个Strong-Type Collection。
针对设计人员对Strong-Type Collection的需求,.NET FRAMEWORK提供了一个CollectionBase的基础类。
下面是一个简单范例,代码中的List是CollectionBase中一个protected IList,它包含CollectionBase 实例中元素的列表。


public class Int16Collection : CollectionBase {
public Int16 this[ int index ] {
get {
return( (Int16) List[index] );
}
set {
List[index] = value;
}
}
public int Add( Int16 value ) {
return( List.Add( value ) );
}
public int IndexOf( Int16 value ) {
return( List.IndexOf( value ) );
}
public void Insert( int index, Int16 value ) {
List.Insert( index, value );
}
public void Remove( Int16 value ) {
List.Remove( value );
}
public bool Contains( Int16 value ) {
return( List.Contains( value ) );
}
}

CodeDOM


它是.net framework中产生程序代码的基础建设,它以对象化方式仿真出程序代码的逻辑,最后交给特定Code Provider对象(e.g. CSharpCodeProvider)产生源程序代码。

CodeCompileUnit是CodeDOM中根容器型对象。
CodeNamespace对象可以产生namespace语句。
CodeTypeDeclaration可以用来产生声明类型的对象,可以处理类、枚举、接口、结构。
CodeMemverField、CodeMemberMethod、CodeMemberProperty和CodeMemberEvent分别可以产生成员变量、方法、属性和事件。
指定CodeMemberMethod的ReturnType可以指定返回值类型,通过添加CodeMethodReturnStatement对象产生return代码。
添加Paramerters可以指定方法传递的参数。

以下是示例代码:


using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;

namespace DesignPattern
{
/// <summary>
/// codedomtest 的摘要说明。
/// </summary>
public class codedomtest : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
//创建根容器对象
CodeCompileUnit unit=new CodeCompileUnit();
//创建产生源代码的Provider对象
CodeDomProvider provider=new CSharpCodeProvider();
//创建产生NameSpace的对象
CodeNamespace cns=new CodeNamespace("MyNamespace");
//创建NameSpace的包含对象
CodeNamespaceImport cnsi=new CodeNamespaceImport("System");
cns.Imports.Add(cnsi);
//创建生成类的对象
CodeTypeDeclaration ctd=new CodeTypeDeclaration("MyClass");
ctd.IsClass=true;
//创建类的成员函数
CodeMemberField cmf=new CodeMemberField(typeof(int),"one");
ctd.Members.Add(cmf);
//创建类的方法
CodeMemberMethod cmm=new CodeMemberMethod();
cmm.Name="getNum";
cmm.ReturnType=new CodeTypeReference(typeof(int));
cmm.Attributes=MemberAttributes.Public;
cmm.Statements.Add(new CodeMethodReturnStatement(new CodeArgumentReferenceExpression("one")));
ctd.Members.Add(cmm);
cns.Types.Add(ctd);
unit.Namespaces.Add(cns);
//将代码生成到d:/test.cs
ICodeGenerator gen=provider.CreateGenerator();
StreamWriter sw=new StreamWriter("d://test.cs",false);
gen.GenerateCodeFromCompileUnit(unit,sw,new CodeGeneratorOptions());
sw.Close();
}
#region Web 窗体设计器生成的代码
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: 该调用是 ASP.NET Web 窗体设计器所必需的。
//
InitializeComponent();
base.OnInit(e);
}

/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
}
生成的test.cs如下:
namespace MyNamespace {
using System;


public class MyClass {

private int one;

public virtual int getNum() {
return one;
}
}
}

Attribute

我的理解为特性。它像标签一样可以贴在类、方法、变量上。我们可以使用它定义设计层的信息或定义运行时信息。
预定义的Attribute要继承自System.Attribute。以下是示例:


[AttributeUsage(AttributeTargets.All,Inherited=false,AllowMultiple=false)]
public class DescribeAttribute:Attribute
{
private string _AddName;
public string AddName
{
get
{
return _AddName;
}
set
{
_AddName=value;
}
}
public DescribeAttribute(string a)
{
_AddName=a;
}
}

AttributeUsage代表了Attribute适用的情况。第一个参数是该Attribute适用的情况,第二个参数代表是否该Attribute会随着继承被继承,第三个参数代表同一目标能否被重复贴上该Attribute。
如下代码定义了一个贴上了以上定义的Attribute的class:


[Describe("This is my Attribute Test.")]
public class AttrTest
{
public AttrTest()
{
}
}

Attribute一般被绑定于Type上,可以通过Type.GetCustomAttributes获得:


DescribeAttribute[] da=(DescribeAttribute[])typeof(AttrTest).GetCustomAttributes(typeof(DescribeAttribute),false);
foreach(DescribeAttribute dada in da)
Response.Write(dada.AddName);

Attribute可以绑定于方法或变量上,下面是将Attribute绑定到方法上的代码:

[Describe("This is a class.")]
public class AttrTest
{
public AttrTest()
{

}
[Describe("This is a method.")]
public void TestMethod()
{

}
}

成员上的方法通过Reflection的MethodInfo.GetCustomAttributes获得(如果获得成员变量上的Attribute就要用FieldInfo类):


foreach(MethodInfo method in typeof(AttrTest).GetMethods())
{
foreach (DescribeAttribute attr in method.GetCustomAttributes(true))
{
Response.Write(attr.AddName);
}
}

Attribute标识符
Attribute标识符可以声明Attribute的放置位置。
[assembly: Help("this a do-nothing assembly")]
以上程序告诉编译器Help属性用于整个程序集。
可用的标识符包括:

assembly
module
type
method
property
event
field
param
return
原创粉丝点击