??xml version="1.0" encoding="utf-8" standalone="yes"?>
基本原理是先徏立Socketq接Q然后发h命o(h)和取回应{码。编码方式采用Encoding ASCII = Encoding.Default;来支持中文文件名?/span>
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO;
namespace PMTSS.Common
{
/// <summary>
/// FTP 操作c?br />
/// </summary>
public class FTP
{
private string strRemoteHost;
private int strRemotePort;
private string strRemotePath;
private string strRemoteUser;
private string strRemotePass;
private Boolean bConnected;
#region 内部变量
/// <summary>
/// 服务器返回的应答信息(包含应答?
/// </summary>
private string strMsg;
/// <summary>
/// 服务器返回的应答信息(包含应答?
/// </summary>
private string strReply;
/// <summary>
/// 服务器返回的应答?br />
/// </summary>
private int iReplyCode;
/// <summary>
/// q行控制q接的socket
/// </summary>
private Socket socketControl;
/// <summary>
/// 传输模式
/// </summary>
private TransferType trType;
/// <summary>
/// 传输模式:二进制类型、ASCIIcd
/// </summary>
public enum TransferType
{
/// <summary>
/// Binary
/// </summary>
Binary,
/// <summary>
/// ASCII
/// </summary>
ASCII
};
/// <summary>
/// 接收和发送数据的~冲?br />
/// </summary>
private static int BLOCK_SIZE = 512;
Byte[] buffer = new Byte[ BLOCK_SIZE];
/// <summary>
/// ~码方式
/// </summary>
Encoding ASCII = Encoding.Default;
#endregion
#region 内部函数
#region 构造函?br />
/// <summary>
/// ~省构造函?br />
/// </summary>
public FTP()
{
strRemoteHost = "";
strRemotePath = "";
strRemoteUser = "";
strRemotePass = "";
strRemotePort = 21;
bConnected = false;
}
/// <summary>
/// 构造函?br />
/// </summary>
/// <param name="remoteHost"></param>
/// <param name="remotePath"></param>
/// <param name="remoteUser"></param>
/// <param name="remotePass"></param>
/// <param name="remotePort"></param>
public FTP( string remoteHost, string remotePath, string remoteUser, string remotePass, int remotePort )
{
strRemoteHost = remoteHost;
strRemotePath = remotePath;
strRemoteUser = remoteUser;
strRemotePass = remotePass;
strRemotePort = remotePort;
Connect();
}
public FTP( string remoteHost, string remotePath, string remoteUser, string remotePass)
{
strRemoteHost = remoteHost;
strRemotePath = remotePath;
strRemoteUser = remoteUser;
strRemotePass = remotePass;
strRemotePort = 21;
Connect();
}
#endregion
#region 登陆
/// <summary>
/// FTP服务器IP地址
/// </summary>
public string RemoteHost
{
get
{
return strRemoteHost;
}
set
{
strRemoteHost = value;
}
}
/// <summary>
/// FTP服务器端?br />
/// </summary>
public int RemotePort
{
get
{
return strRemotePort;
}
set
{
strRemotePort = value;
}
}
/// <summary>
/// 当前服务器目?br />
/// </summary>
public string RemotePath
{
get
{
return strRemotePath;
}
set
{
strRemotePath = value;
}
}
/// <summary>
/// d用户账号
/// </summary>
public string RemoteUser
{
set
{
strRemoteUser = value;
}
}
/// <summary>
/// 用户d密码
/// </summary>
public string RemotePass
{
set
{
strRemotePass = value;
}
}
/// <summary>
/// 是否d
/// </summary>
public bool Connected
{
get
{
return bConnected;
}
}
#endregion
#region 链接
/// <summary>
/// 建立q接
/// </summary>
public void Connect()
{
socketControl = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(RemoteHost), strRemotePort);
// 链接
try
{
socketControl.Connect(ep);
}
catch(Exception)
{
throw new IOException("Couldn't connect to remote server");
}
// 获取应答?br />
ReadReply();
if(iReplyCode != 220)
{
DisConnect();
throw new IOException(strReply.Substring(4));
}
// 登陆
SendCommand("USER "+strRemoteUser);
if( !(iReplyCode == 331 || iReplyCode == 230) )
{
CloseSocketConnect();//关闭q接
throw new IOException(strReply.Substring(4));
}
if( iReplyCode != 230 )
{
SendCommand("PASS "+strRemotePass);
if( !(iReplyCode == 230 || iReplyCode == 202) )
{
CloseSocketConnect();//关闭q接
throw new IOException(strReply.Substring(4));
}
}
bConnected = true;
// 切换到目?br />
ChDir(strRemotePath);
}
/// <summary>
/// 关闭q接
/// </summary>
public void DisConnect()
{
if( socketControl != null )
{
SendCommand("QUIT");
}
CloseSocketConnect();
}
#endregion
#region 传输模式
/// <summary>
/// 讄传输模式
/// </summary>
/// <param name="ttType">传输模式</param>
public void SetTransferType(TransferType ttType)
{
if(ttType == TransferType.Binary)
{
SendCommand("TYPE I");//binarycd传输
}
else
{
SendCommand("TYPE A");//ASCIIcd传输
}
if (iReplyCode != 200)
{
throw new IOException(strReply.Substring(4));
}
else
{
trType = ttType;
}
}
/// <summary>
/// 获得传输模式
/// </summary>
/// <returns>传输模式</returns>
public TransferType GetTransferType()
{
return trType;
}
#endregion
#region 文g操作
/// <summary>
/// 获得文g列表
/// </summary>
/// <param name="strMask">文g名的匚w字符?lt;/param>
/// <returns></returns>
public string[] Dir(string strMask)
{
// 建立链接
if(!bConnected)
{
Connect();
}
//建立q行数据q接的socket
Socket socketData = CreateDataSocket();
//传送命?br /> SendCommand("NLST " + strMask);
//分析应答代码
if(!(iReplyCode == 150 || iReplyCode == 125 || iReplyCode == 226))
{
throw new IOException(strReply.Substring(4));
}
//获得l果
strMsg = "";
while(true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
strMsg += ASCII.GetString(buffer, 0, iBytes);
if(iBytes < buffer.Length)
{
break;
}
}
char[] seperator = {'\n'};
string[] strsFileList = strMsg.Split(seperator);
socketData.Close();//数据socket关闭时也?x)有q回?br />
if(iReplyCode != 226)
{
ReadReply();
if(iReplyCode != 226)
{
throw new IOException(strReply.Substring(4));
}
}
return strsFileList;
}
/// <summary>
/// 获取文g大小
/// </summary>
/// <param name="strFileName">文g?lt;/param>
/// <returns>文g大小</returns>
private long GetFileSize(string strFileName)
{
if(!bConnected)
{
Connect();
}
SendCommand("SIZE " + Path.GetFileName(strFileName));
long lSize=0;
if(iReplyCode == 213)
{
lSize = Int64.Parse(strReply.Substring(4));
}
else
{
throw new IOException(strReply.Substring(4));
}
return lSize;
}
/// <summary>
/// 删除
/// </summary>
/// <param name="strFileName">待删除文件名</param>
public void Delete(string strFileName)
{
if(!bConnected)
{
Connect();
}
SendCommand("DELE "+strFileName);
if(iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
/// <summary>
/// 重命?如果新文件名与已有文仉?覆盖已有文?
/// </summary>
/// <param name="strOldFileName">旧文件名</param>
/// <param name="strNewFileName">新文件名</param>
public void Rename(string strOldFileName,string strNewFileName)
{
if(!bConnected)
{
Connect();
}
SendCommand("RNFR "+strOldFileName);
if(iReplyCode != 350)
{
throw new IOException(strReply.Substring(4));
}
// 如果新文件名与原有文仉?覆盖原有文?br />
SendCommand("RNTO "+strNewFileName);
if(iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
#endregion
#region 上传和下?br />
/// <summary>
/// 下蝲一Ҏ(gu)?br />
/// </summary>
/// <param name="strFileNameMask">文g名的匚w字符?lt;/param>
/// <param name="strFolder">本地目录(不得以\l束)</param>
public void Get(string strFileNameMask,string strFolder)
{
if(!bConnected)
{
Connect();
}
string[] strFiles = Dir(strFileNameMask);
foreach(string strFile in strFiles)
{
if(!strFile.Equals(""))//一般来说strFiles的最后一个元素可能是I字W串
{
Get(strFile,strFolder,strFile);
}
}
}
/// <summary>
/// 下蝲一个文?br />
/// </summary>
/// <param name="strRemoteFileName">要下载的文g?lt;/param>
/// <param name="strFolder">本地目录(不得以\l束)</param>
/// <param name="strLocalFileName">保存在本地时的文件名</param>
public void Get(string strRemoteFileName,string strFolder,string strLocalFileName)
{
if(!bConnected)
{
Connect();
}
SetTransferType(TransferType.Binary);
if (strLocalFileName.Equals(""))
{
strLocalFileName = strRemoteFileName;
}
if(!File.Exists(strLocalFileName))
{
Stream st = File.Create(strLocalFileName);
st.Close();
}
FileStream output = new
FileStream(strFolder + "\\" + strLocalFileName,FileMode.Create);
Socket socketData = CreateDataSocket();
SendCommand("RETR " + strRemoteFileName);
if(!(iReplyCode == 150 || iReplyCode == 125
|| iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
while(true)
{
int iBytes = socketData.Receive(buffer, buffer.Length, 0);
output.Write(buffer,0,iBytes);
if(iBytes <= 0)
{
break;
}
}
output.Close();
if (socketData.Connected)
{
socketData.Close();
}
if(!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if(!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
}
/// <summary>
/// 上传一Ҏ(gu)?br />
/// </summary>
/// <param name="strFolder">本地目录(不得以\l束)</param>
/// <param name="strFileNameMask">文g名匹配字W?可以包含*?)</param>
public void Put(string strFolder,string strFileNameMask)
{
string[] strFiles = Directory.GetFiles(strFolder,strFileNameMask);
foreach(string strFile in strFiles)
{
//strFile是完整的文g?包含路径)
Put(strFile);
}
}
/// <summary>
/// 上传一个文?br />
/// </summary>
/// <param name="strFileName">本地文g?lt;/param>
public void Put(string strFileName)
{
if(!bConnected)
{
Connect();
}
Socket socketData = CreateDataSocket();
SendCommand("STOR "+Path.GetFileName(strFileName));
if( !(iReplyCode == 125 || iReplyCode == 150) )
{
throw new IOException(strReply.Substring(4));
}
FileStream input = new
FileStream(strFileName,FileMode.Open);
int iBytes = 0;
while ((iBytes = input.Read(buffer,0,buffer.Length)) > 0)
{
socketData.Send(buffer, iBytes, 0);
}
input.Close();
if (socketData.Connected)
{
socketData.Close();
}
if(!(iReplyCode == 226 || iReplyCode == 250))
{
ReadReply();
if(!(iReplyCode == 226 || iReplyCode == 250))
{
throw new IOException(strReply.Substring(4));
}
}
}
#endregion
#region 目录操作
/// <summary>
/// 创徏目录
/// </summary>
/// <param name="strDirName">目录?lt;/param>
public void MkDir(string strDirName)
{
if(!bConnected)
{
Connect();
}
SendCommand("MKD "+strDirName);
if(iReplyCode != 257)
{
throw new IOException(strReply.Substring(4));
}
}
/// <summary>
/// 删除目录
/// </summary>
/// <param name="strDirName">目录?lt;/param>
public void RmDir(string strDirName)
{
if(!bConnected)
{
Connect();
}
SendCommand("RMD "+strDirName);
if(iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
}
/// <summary>
/// 改变目录
/// </summary>
/// <param name="strDirName">新的工作目录?lt;/param>
public void ChDir(string strDirName)
{
if(strDirName.Equals(".") || strDirName.Equals(""))
{
return;
}
if(!bConnected)
{
Connect();
}
SendCommand("CWD "+strDirName);
if(iReplyCode != 250)
{
throw new IOException(strReply.Substring(4));
}
this.strRemotePath = strDirName;
}
#endregion
/// <summary>
/// 一行应{字W串记录在strReply和strMsg
/// 应答码记录在iReplyCode
/// </summary>
private void ReadReply()
{
strMsg = "";
strReply = ReadLine();
iReplyCode = Int32.Parse(strReply.Substring(0,3));
}
/// <summary>
/// 建立q行数据q接的socket
/// </summary>
/// <returns>数据q接socket</returns>
private Socket CreateDataSocket()
{
SendCommand("PASV");
if(iReplyCode != 227)
{
throw new IOException(strReply.Substring(4));
}
int index1 = strReply.IndexOf('(');
int index2 = strReply.IndexOf(')');
string ipData =
strReply.Substring(index1+1,index2-index1-1);
int[] parts = new int[6];
int len = ipData.Length;
int partCount = 0;
string buf="";
for (int i = 0; i < len && partCount <= 6; i++)
{
char ch = Char.Parse(ipData.Substring(i,1));
if (Char.IsDigit(ch))
buf+=ch;
else if (ch != ',')
{
throw new IOException("Malformed PASV strReply: " +
strReply);
}
if (ch == ',' || i+1 == len)
{
try
{
parts[partCount++] = Int32.Parse(buf);
buf="";
}
catch (Exception)
{
throw new IOException("Malformed PASV strReply: " +
strReply);
}
}
}
string ipAddress = parts[0] + "."+ parts[1]+ "." +
parts[2] + "." + parts[3];
int port = (parts[4] << 8) + parts[5];
Socket s = new
Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
IPEndPoint ep = new
IPEndPoint(IPAddress.Parse(ipAddress), port);
try
{
s.Connect(ep);
}
catch(Exception)
{
throw new IOException("Can't connect to remote server");
}
return s;
}
/// <summary>
/// 关闭socketq接(用于d以前)
/// </summary>
private void CloseSocketConnect()
{
if(socketControl!=null)
{
socketControl.Close();
socketControl = null;
}
bConnected = false;
}
/// <summary>
/// dSocketq回的所有字W串
/// </summary>
/// <returns>包含应答码的字符串行</returns>
private string ReadLine()
{
while(true)
{
int iBytes = socketControl.Receive(buffer, buffer.Length, 0);
strMsg += ASCII.GetString(buffer, 0, iBytes);
if(iBytes < buffer.Length)
{
break;
}
}
char[] seperator = {'\n'};
string[] mess = strMsg.Split(seperator);
if(strMsg.Length > 2)
{
strMsg = mess[mess.Length-2];
//seperator[0]?0,换行W是?3?l成?分隔?0后面虽没有字W串,
//但也?x)分配?f)I字W串l后?也是最后一?字符串数l?
//所以最后一个mess是没用的I字W串
//但ؓ(f)什么不直接取mess[0],因ؓ(f)只有最后一行字W串应答码与信息之间有空?br />
}
else
{
strMsg = mess[0];
}
if(!strMsg.Substring(3,1).Equals(" "))//q回字符串正的是以应答??20开?后面接一I格,再接问候字W串)
{
return ReadLine();
}
return strMsg;
}
/// <summary>
/// 发送命令ƈ获取应答码和最后一行应{字W串
/// </summary>
/// <param name="strCommand">命o(h)</param>
private void SendCommand(string strCommand)
{
Byte[] cmdBytes = ASCII.GetBytes((strCommand + "\r\n").ToCharArray());
socketControl.Send(cmdBytes, cmdBytes.Length, 0);
ReadReply();
}
#endregion
}
}
1.清单 11-1. 索引指示器的例子QIntIndexer.cs |
using System; /// /// A simple indexer example. /// class IntIndexer { private string[] myData; public IntIndexer(int size) { myData = new string[size]; for (int i=0; i < size; i++) { myData[i] = "empty"; } } public string this[int pos] { get { return myData[pos]; } set { myData[pos] = value; } } static void Main(string[] args) { int size = 10; IntIndexer myInd = new IntIndexer(size); myInd[9] = "Some Value"; myInd[3] = "Another Value"; myInd[5] = "Any Value"; Console.WriteLine("\nIndexer Output\n"); for (int i=0; i < size; i++) { Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]); } } } |
说明 |
Indexer Output myInd[0]: empty myInd[1]: empty myInd[2]: empty myInd[3]: Another Value myInd[4]: empty myInd[5]: Any Value myInd[6]: empty myInd[7]: empty myInd[8]: empty myInd[9]: Some Value |
2.清单 11-2. 重蝲的烦引指C器: OvrIndexer.cs |
using System; /// /// Implements overloaded indexers. /// class OvrIndexer { private string[] myData; private int arrSize; public OvrIndexer(int size) { arrSize = size; myData = new string[size]; for (int i=0; i < size; i++) { myData[i] = "empty"; } } public string this[int pos] { get { return myData[pos]; } set { myData[pos] = value; } } public string this[string data] { get { int count = 0; for (int i=0; i < arrSize; i++) { if (myData[i] == data) { count++; } } return count.ToString(); } set { for (int i=0; i < arrSize; i++) { if (myData[i] == data) { myData[i] = value; } } } } static void Main(string[] args) { int size = 10; OvrIndexer myInd = new OvrIndexer(size); myInd[9] = "Some Value"; myInd[3] = "Another Value"; myInd[5] = "Any Value"; myInd["empty"] = "no value"; Console.WriteLine("\nIndexer Output\n"); for (int i=0; i < size; i++) { Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]); } Console.WriteLine("\nNumber of \"no value\" entries: {0}", myInd["no value"]); } } |
说明 |
Indexer Output myInd[0]: no value myInd[1]: no value myInd[2]: no value myInd[3]: Another Value myInd[4]: no value myInd[5]: Any Value myInd[6]: no value myInd[7]: no value myInd[8]: no value myInd[9]: Some Value Number of "no value" entries: 7 |
public object this[int param1, ..., int paramN] { get { // process and return some class data } set { // process and assign some class data } } |
public delegate void MyDelegate(string str);
?br />1.委托的定义和Ҏ(gu)的定义类|只是在前面加了一个delegate,但委托不是方法,它是一U类型。是一U特D的cd,看成是一U新的对象类型比较好理解。用于对与该委托有相
同签名的Ҏ(gu)调用?br />2.委托相当于C++中的函数指针Q但它是cd安全的?br />3.委托是从System.DelegatezQ但不能象定义常规类型一L(fng)接从System.DelegatezQ对委托的声明只能通过上面的声明格式进行定义。关键字delegate通知~译器这是一
个委托类型,从而在~译的时候对该类q行装,对这一q程C#定义了专门的语法来处理这一q程?br />4.不能从一个委托类型进行派生,因ؓ(f)它也是默认sealed?br />5.委托卛_以对静态方法进行调用也可以对实例方法进行调用?br />6.每个委托cd包含一个自q调用列表Q当l合一个委托或从一个委托中删除一个委托时都将产生个新的调用列表?br />7.两个不同cd的委托即使它们有相同的签名和q回|但还是两个不同类型的委托。但其实在用中可看作是相同的?/font>
委托的比?/font>
C#中对委托定义了两个操作符 == ?!=
在以下情况下两个委托是相{的Q?br />1.当两个委托都同时为null的时?br />2.当两个委托都不ؓ(f)null?下列情况下是相等的?br />a.当两个委托的各自的调用列表只含有一个入口点的时?br /> 在下列情况下是相{的
(1) 调用同一对象的同一静态方?br /> (2) 调用同一对象的同一实例Ҏ(gu)
b.当两个委托具有多个入口点?br /> 在下列情况下是相{的
(1)只有当它们调用列表中的调用的Ҏ(gu)按顺序都一一对应相同的对象及(qing)对象的同一Ҏ(gu)的时?/font>
如上所q的两个不同cd的委托但是它们具有相同的{和返回值时Q只要满上q条件的Q即使它们类型不同,但比较的l果也是相同的?/font>
委托的异常处?/font>
当调用该委托的方法中发生了异常时Q首先在调用该委托的Ҏ(gu)中搜寻catch语句块。如果没有,则去该委托调用的Ҏ(gu)中去L有没有catch语句块,q和调用Ҏ(gu)发生异常的处
理是一L(fng)?/font>
当调用一个ؓ(f)null的委托即委托中列表中不存在调用方法时Q将发生NullRefrenceException
委托的注意点:
当一个委托有多个入口点的时?调用委托依该委托的调用列表中的Ҏ(gu)的顺序依ơ调?q些Ҏ(gu)׃n一个参数集?所以当委托有返回值的时候调用完q个委托后的q回值是最
后一个方法的q回值或是有out参数.如果该委托的参数为ref(引用cd),那么在招待第一个方法的时候如果对q个参数的值有所改变,那么q个改变会(x)影响到后面的Ҏ(gu)调用.
委托的一个例?/font>
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// 创徏一个委托实例,装Ccȝ静态方法M1
MyDelegate d1 = new MyDelegate(C.M1);
d1("D1"); // M1
// 创徏一个委托实例,装Ccȝ静态方法M2
MyDelegate d2 = new MyDelegate(C.M2);
d2("D2"); // M2
// 创徏一个委托实例,装Ccȝ实例Ҏ(gu)M3
MyDelegate d3 = new MyDelegate(new C().M3);
d3("D3"); // M3
// 从一个委托d3创徏一个委托实?br /> MyDelegate d4 = new MyDelegate(d3);
d4("D4"); // M3
// l合两个委托
MyDelegate d5 = d1 + d2;
d5 += d3;
d5("D5"); // M1,M2,M3
// 从组合委托中删除d3
MyDelegate d6 = d5 - d3;
d6("D6"); // M1,M2
d6 -= d3; // 虽然d6调用列表中已l没有d3了,但这样只是不可能的移除没有错误发?br /> d6("D6"); // M1,M2
d6 -= d6;
//d6("D6"); 此时d6的调用列表ؓ(f)I,d6为null,所以引发System.NullReferenceException
MyDelegate d7 = new MyDelegate(C1.P1);
d7("D7"); // C1.P1
MyDelegate d8 = new MyDelegate(new C2().P1);
d8("D8"); // C2.P1
}
}
// 声明一个委托MyDelegate
public delegate void MyDelegate(string str);
public class C
{
public static void M1(string str)
{
Console.WriteLine("From:C.M1: {0}", str);
}
public static void M2(string str)
{
Console.WriteLine("From:C.M2: {0}", str);
}
public void M3(string str)
{
Console.WriteLine("From:C.M3: {0}", str);
}
}
public class C1
{
public static void P1(string str)
{
Console.WriteLine("From:C1.P1: {0}", str);
}
}
public class C2
{
public void P1(string str)
{
Console.WriteLine("From:C2.P1: {0}", str);
}
}
}
事g委托
事g概述
事g是当对象或cȝ态发生改变时Q对象或cd出的信息或通知。发Z息的对象或类UCؓ(f)"事g?,对事件进行处理的Ҏ(gu)UCؓ(f)"接收?,通常事g源在发出状态改变信息时,?/font>
q不知道由哪个事件接收者来处理.q就需要一U管理机制来协调事g源和接收?C++中通过函数指针来完成的.在C#中事件用委托来发时调用的Ҏ(gu)提供cd安全的封?/font>
事g的声?/font>
1.声明一个委?br />public delegate void EventHandler(object sender, System.EventArgs e);
2.声明一个事?br />public event EventHandler Changed;
3.引发一个事?br />public OnChanged(EnventArgs e)
{
if ( Changed != null)
{
Changed(this,e);
}
}
4.定义事g处理E序
public MyText_OnChanged(Object sender,EventArgs e)
{
...
}
5.订阅事g(事件处理程序添加到事g的调用列表中)
myText.Changed += EventHandler(MyText_OnChanged);
下面的一个小例子说明了怎样定义一个完整的事g机制:
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyText myText = new MyText();
// 事件处理程序添加到事g的调用列表中(即事件布U?
myText.Changed += new MyText.ChangedEventHandler(myText_Changed);
string str = "";
while (str != "quit")
{
Console.WriteLine("please enter a string:");
str = Console.ReadLine();
myText.Text = str;
}
}
// 对Change事g处理的程?br /> private static void myText_Changed(object sender, EventArgs e)
{
Console.WriteLine("text has been changed :{0}\n" ,((MyText)sender).Text);
}
}
public class MyText
{
private string _text = "";
// 定义事g的委?br /> public delegate void ChangedEventHandler(object sender, EventArgs e);
// 定义一个事?br /> public event ChangedEventHandler Changed;
// 用以触发Change事g
protected virtual void OnChanged(EventArgs e)
{
if (this.Changed != null)
this.Changed(this, e);
}
// Text属?br /> public string Text
{
get { return this._text; }
set
{
this._text = value;
// 文本改变时触发Change事g
this.OnChanged(new EventArgs());
}
}
}
}
1.面向对象的思想主要包括什么?
2.什么是ASP.net中的用户控g
3.什么叫应用E序域?什么是受管制的代码Q什么是强类型系l?什么是装箱和拆?什么是重蝲QCTS、CLS和CLR分别作何解释Q?br /> 4.列D一下你所了解的XML技术及(qing)其应?br /> 5.值类型和引用cd的区别?写出C#的样例代码?br /> 6.ADO.net中常用的对象有哪些?分别描述一下?br /> 7.如何理解委托Q?br /> 8.C#中的接口和类有什么异同?br /> 9.。net中读写数据库需要用到哪些类Q他们的作用
10.UDPq接和TCPq接的异同?br /> 11.ASP.net的n份验证方式有哪些Q分别是什么原理?
12.q程和线E分别怎么理解Q?br /> 13.什么是code-Behind技术?br /> 14.zd目录的作用?br /> 15..net中读写XML的类都归属于哪些命名I间Q?br /> 16.解释一下UDDI、WSDL的意义及(qing)其作用?br /> 17.什么是SOAP,有哪些应用?br /> 18.如何部v一个ASP.net面?br /> 19.如何理解.net中的垃圾回收机制?br /> 20.常用的调用webserviceҎ(gu)有哪些?
1 l承 多?装
2 用户控g. 不会(x)说懂得做
3 装箱和拆发?值类型向引用cd转换,和引用类型向值类型{ 重蝲:同一个函数参C?br /> 4.xml可以用来做网?xslt) xml可以当作数据?xml可以用来保存对象的系列化
5值类?没有什么好说的.引用cd用处是返回两个以上参数的时候比较好?ref out 我常用的是out不要先赋?br /> 6 ado.net 我直接用 sqlhelper?有connection command q有参数
7 回调机制比较有用?在net中采用了委托.
8 接口,是可以多l承,cd有单l承.接口了你必须实现,而没有具本实现的Ҏ(gu)和虚cL点相?br /> 9 datareader dataset q有一个不太常?br /> 10 udp不要实现什么三ơ握?
11 asp.netw䆾验证最常用q是以前的sessionҎ(gu). form验证没有用过. 微Y的哪个也没有用过
12 q程单理解ؓ(f)单个E序?按ctrl+alt+del)可以看到?它至有一个主U程 .
13 代码后置..不懂得讲
14 zd目录.. 完全不会(x)
15 system.xml (system.io创徏目录的时候用)
16 q个也是web服务里的东西.
17 soap单协?我只知道.web服务是基于它之上?br /> 18 部置一个页? 也就是说没有代码是直接写在aspx中的?只接攑֜IIS的虚拟目录下p?当然要asp.net支持
19 垃圾回收..一般的只要掌握.非托对象要记得释放资源p了吧.
20 直接在vs.net里面引用O(jin)K?它会(x)自己生成一个代理类
1. 填空: (1)面向对象的语ah___l承性、_装___性、___多态性?br /> (2)能用foreach遍历讉K的对象需要实?IEnumerable接口或声明GetEnumerable
Ҏ(gu)的类型?br />
(3)列DADO.net中的五个主要对象Command、Connection、DataSet、DataSetCommand、DataReader?br /> 2. 不定w择Q?br /> (1) 以下叙述正确的是Q?
A. 接口中可以有虚方法。 ?B. 一个类可以实现多个接口?
C. 接口不能被实例化。 ?D. 接口中可以包含已实现的方法?
(2) 从数据库d记录Q你可能用到的方法有Q?br /> A. ExecuteNonQuery B. ExecuteScalar
C. Fill D. ExecuteReader
3. q?private?protected?public?internal 修饰W的讉K权限?/font>
4. 写出一条Sql语句Q?取出表A中第31到第40记录QSQLServer, 以自动增长的ID作ؓ(f)主键,
注意QID可能不是q箋的。)
5 .列DASP.NET 面之间传递值的几种方式?
6. 写出E序的输出结?
class Class1 {
private string str = "Class1.str";
private int i = 0;
static void StringConvert(string str) {
str = "string being converted.";
}
static void StringConvert(Class1 c) {
c.str = "string being converted.";
}
static void Add(int i) {
i++;
}
static void AddWithRef(ref int i) {
i++;
}
static void Main() {
int i1 = 10;
int i2 = 20;
string str = "str";
Class1 c = new Class1();
Add(i1);
AddWithRef(ref i2);
Add(c.i);
StringConvert(str);
StringConvert(c);
Console.WriteLine(i1);
Console.WriteLine(i2);
Console.WriteLine(c.i);
Console.WriteLine(str);
Console.WriteLine(c.str);
}
}
?NET Framework中,Hashtable是System.Collections命名I间提供的一个容器,用于处理和表现类似keyvalue的键值对Q其中key通常可用来快速查找,同时key是区分大写Qvalue用于存储对应于key的倹{Hashtable中keyvalue键值对均ؓ(f)objectcdQ所以Hashtable可以支持Mcd的keyvalue键值对.
?哈希表的单操?/font>
在哈希表中添加一个keyvalue键值对QHashtableObject.Add(key,value);
在哈希表中去除某个keyvalue键值对QHashtableObject.Remove(key);
从哈希表中移除所有元素:(x) HashtableObject.Clear();
判断哈希表是否包含特定键keyQ ?HashtableObject.Contains(key);
下面控制台程序将包含以上所有操作:(x)
using System;
using System.Collections; file使用HashtableӞ必须引入q个命名I间
class hashtable
{
public static void Main()
{
Hashtable ht=new Hashtable(); file创徏一个Hashtable实例
ht.Add(E,e);dkeyvalue键值对
ht.Add(A,a);
ht.Add(C,c);
ht.Add(B,b);
注意Qkey值必d一?/font>
string s=(string)ht[A];
if(ht.Contains(E)) file判断哈希表是否包含特定键,其返回gؓ(f)true或false
Console.WriteLine(the E keyexist);
ht.Remove(C);U除一个keyvalue键值对
Console.WriteLine(ht[A]);此处输出a
ht.Clear();U除所有元?br /> Console.WriteLine(ht[A]); file此处不?x)有M输出
}
}
?遍历哈希?/font>
遍历哈希表需要用到DictionaryEntry ObjectQ代码如下:(x)
for(DictionaryEntry de in ht) filehtZ个Hashtable实例
{
Console.WriteLine(de.Key);de.Key对应于keyvalue键值对key
Console.WriteLine(de.Value);de.Key对应于keyvalue键值对value
}
?对哈希表q行排序
对哈希表q行排序在这里的定义是对keyvalue键值对中的key按一定规则重新排列,但是实际上这个定义是不能实现的,因ؓ(f)我们无法直接在Hashtableq行对keyq行重新排列Q如果需要Hashtable提供某种规则的输出,可以采用一U变通的做法Q?br /> ArrayList akeys=new ArrayList(ht.Keys); file别忘了导入System.Collections
akeys.Sort(); file按字母顺序进行排?br /> for(string skey in akeys)
{
Console.Write(skey + );
Console.WriteLine(ht[skey]);排序后输?br /> }
protected static WindowsIdentity CreateIdentity(string User, string Domain, string Password)
{
// The Windows NT user token.
IntPtr tokenHandle = new IntPtr(0);
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_NETWORK = 3;
tokenHandle = IntPtr.Zero;
// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(User, Domain, Password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);
if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
throw new Exception("LogonUser failed with error code: " + ret);
}
System.Diagnostics.Debug.WriteLine("Created user token: " + tokenHandle);
//The WindowsIdentity class makes a new copy of the token.
//It also handles calling CloseHandle for the copy.
WindowsIdentity id = new WindowsIdentity(tokenHandle);
CloseHandle(tokenHandle);
return id;
}
[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private extern static bool CloseHandle(IntPtr handle);
}
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml;
using System.Xml.XPath;
public partial class _Default : System.Web.UI.Page
{
public string[] x = new string[4];
protected void Page_Load(object sender, EventArgs e)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath("table.xml"));//你的xml文g
XmlNodeList xmlList = xmlDoc.SelectSingleNode("MapSheet").ChildNodes;
foreach (XmlNode xmlNo in xmlList)
{
//XmlNodeList xe = (XmlNodeList)xmlNo;
XmlElement xe = (XmlElement)xmlNo;
{
if (xe.Name == "TableName")
{
y[0] = xe.InnerText;
}
if (xe.Name == "DataSource")
{
y[1] = xe.InnerText;
}
if (xe.Name == "UserName")
{
y[2] = xe.InnerText;
}
if (xe.Name == "Password")
{
y[3] = xe.InnerText;
}
}
}
TextBox1.Text=y[0];
TextBox2.Text = y[1];
TextBox3.Text = y[2];
TextBox4.Text = y[3];
}
}该程序已l过试Q没有问题?/font>
xmldoc = new system.xml.xmldocument ( ) ; |
◇在xml的文档的最头部加入xml的声明段落:(x)
利用"xmldocument"cM?"createnode" Ҏ(gu)可以创徏一个指定类型的xml节点Q?createnode" Ҏ(gu)的调用方法d有三U,在本文中使用的其一般的Ҏ(gu)Q具体语法如下:(x)
xmldocument.createnode method ( xmlnodetype , string , string ) |
然后在利?xmldocument"cM?appendchild"Ҏ(gu)在xml文档中加入此节点Q用cQ在xml文档中加入声明段落实现的语句如下Q?/font>
xmlnode = xmldoc.createnode ( xmlnodetype.xmldeclaration , "" , "" ) ; xmldoc.appendchild ( xmlnode ) ; |
◇ؓ(f)xml文档加入元素QelementQ:(x)
加入数据内容是通过元素Q在"xmldocument"cM提供了二个方法:(x)"createelement"?createtextnode"。其中第一个方法是在xml中创Z个元素,另外一个方法是为创建的元素指定文本倹{下面是Z面创建的xml文档加入一个根元素。?/font>
xmlelem = xmldoc.createelement ( "" , "root" , "" ) ; xmltext = xmldoc.createtextnode ( "root text" ) ; |
注释Q其?xmlelem"是创建的"xmlelement"对象Q?xmltext"?xmltext"对象
有了创徏一个xml元素的例子,可以根据xml文档中数据的不同的结构来创徏其他的数据了。?br />
2.cQ创建xml文档的第一U方法的源程序代码(no1.csQ:(x)
using system ; using system.xml ; class mainclass { xmldocument xmldoc ; xmlnode xmlnode ; xmlelement xmlelem ; xmlelement xmlelem2 ; xmltext xmltext ;
static void main ( string [ ] args )
{
{ |
3.cQ创建xml文档的第二种Ҏ(gu)Q?/font>
在介l完W一U方法以后,我想每一个读者都感觉到用cQ创建xml文档是一Ҏ(gu)较烦杂的工作了,因ؓ(f)不仅要了解创建的知识Q还要了解文档的l构Q这样创建的q程是一步一步的了。下面就来介l一U比较容易的创徏Ҏ(gu)Q这U创建方法是直接定义xml文档Q然后把他保存到文g中就可以了。?br /> ◇创Z个xml文档Q?br /> q一点和W一U方法一P在这里就不介l了。?br />
◇通过"xmldocument"cM?loadxml"Ҏ(gu)Q直接在文档中加入想要加入的xml数据。当然你加入的xml应该W合xml的语法,不然产生的文件也没有什么意义了。下面是加入xml的具体代码:(x)
doc.loadxml ( "<employees> " + "<no1>" + "<name>ma jin hu</name>" + "<zip> 239000 </zip>" + "<address>feng huang street</address>" + "<city>chu zhou city</city>" + "<state> anhui </state>" + "</no1>" + "<no2>" + "<name>wang tian</name>" + "<zip> 239000 </zip>" + "<address>lang ya street</address>" + "<city>he fei city</city>" + "<state> anhui </state>" + "</no2>" + "<no3>" + "<name>zou wen biao</name>" + "<zip> 100000 </zip>" + "<address>sai di street</address>" + "<city>bei jin city</city>" + "<state>bei jin</state>" + "</no3>" + "</employees>" ) ; |
把保存xml文档到文件中Q?br /> 保存xml文档是通过"xmldocument"cM?save"Ҏ(gu)来实现的。具体如下:(x)
doc.save ( "data.xml" ) ; |
◇cQ创建xml文档的第二种Ҏ(gu)的源E序代码Qno2.csQ:(x)
using system ; using system.io ; using system.xml; public class sample { public static void main ( ) { //创徏一个xmldocument对象 xmldocument doc = new xmldocument ( ) ; doc.loadxml ( "<employees> " + "<no1>" + "<name>ma jin hu</name>" + "<zip> 239000 </zip>" + "<address>feng huang street</address>" + "<city>chu zhou city</city>" + "<state> anhui </state>" + "</no1>" + "<no2>" + "<name>wang tian</name>" + "<zip> 239000 </zip>" + "<address>lang ya street</address>" + "<city>he fei city</city>" + "<state> anhui </state>" + "</no2>" + "<no3>" + "<name>zou wen biao</name>" + "<zip> 100000 </zip>" + "<address>sai di street</address>" + "<city>bei jin city</city>" + "<state>bei jin</state>" + "</no3>" + "</employees>" ) ; //保存q个文档到文件中 doc.save ( "data.xml" ) ; } } |
用cQ创建xml文档的方法其实有很多Q在q里只是选取了二U比较典型的Ҏ(gu)加以介绍。但无论那一U方法,cQ在创徏xml的时候都需要用?net framework sdk。所以了解ƈ掌握q个cd中的内容对于cQ编E是十分必要的,在下面我们将来介l一下用cQ读取xml中的数据Q通过q你?x)发玎ͼcQ又是利用这个类库实现这个功能的。?br />
?/b>.cQ读取xml文gQ?/font>
本节用cQ来d本文中用W二U方法创建的xml文gQ编译no2.cs后,执行?data.xml"文gQ其?data.xml"文g的数据结构如下:(x)
<employees> <no1> <name>ma jin hu</name> <zip> 239000 </zip> <address>feng huang street</address> <city>chu zhou city</city> <state> anhui </state> </no1> <no2> <name>wang tian</name> <zip> 239000 </zip> <address>lang ya street</address> <city>he fei city</city> <state> anhui </state> </no2> <no3> <name>zou wen biao</name> <zip> 100000 </zip> <address>sai di street</address> <city>bei jin city</city> <state>bei jin</state> </no3> </employees> |
在下面的内容中,我们利用cQ读取此文gQƈ用listviewlg按照数据l构l显C出来。下图是d此xml后的q行界面Q?br /> ?1QcQ读取xml后的q行界面
要正读取xml数据Q首先要了解xml的结构。根据上面的xml文gQ可以知道此xml包含三个数据Q下面就来看如何dq三条数据:(x)
◇装入xml文gQŞ成数据流Q?br /> 通过创徏一?xmldocument"对象Q然后利?load"Ҏ(gu)Q可以把xml文g装入Q具体如下:(x)
xmldocument doc = new xmldocument ( ) ; // 装入指定的xml文档 doc.load ( "c:\\data.xml" ) ; |
◇读取xml文gQƈ昄出来Q?br /> dxml是通过创徏"xmlnodereader"对象来实现的Q?xmlnodereader"对象主要是用来可以读取xml的节Ҏ(gu)据。在本文的程序中使用C一?xmlnodereader"的属性,譬如"nodetype"属性,用来判断d得节Ҏ(gu)什么类型?value"是节点的倹{下面是dxml文gq显C在listview中的实现代码Q其中listview1是已l创建listviewlgQ?/font>
while ( reader.read ( ) ) { //判断当前d得节点类?br />switch ( reader.nodetype ) { case xmlnodetype.element : s = reader.name ; break ; case xmlnodetype.text : if ( s.equals ( "name" ) ) myitem = listview1.items.add ( reader.value ) ; else myitem.subitems.add ( reader.value ) ; break ; } } |
?cQ读取xml的文件的源程序代码(read.csQ:(x)
在了解了上面的内容以后,可以得到用cQ读取指定xml文g的完整代码,具体如下Q?/font>
using system ; using system.drawing ; using system.collections ; using system.componentmodel ; using system.windows.forms ; using system.data ; using system.xml ; public class form1 : form { private button button1 ; private listview listview1 ; private system.componentmodel.container components = null ; public form1 ( ) { //初始化窗体中的各个组?br />initializecomponent ( ) ; } //清除E序中用过的资?br />protected override void dispose ( bool disposing ) { if ( disposing ) { if ( components != null ) { components.dispose ( ) ; } } base.dispose ( disposing ) ; } private void initializecomponent ( ) { button1 = new button ( ) ; listview1 = new listview ( ) ; suspendlayout ( ) ; button1.anchor = ( ( anchorstyles.bottom | anchorstyles.left ) | anchorstyles.right ) ; button1.location = new point ( 240 , 296 ) ; button1.name = "button1" ; button1.size = new size ( 112 , 37 ) ; button1.tabindex = 0 ; button1.text = "dxml文档" ; button1.click += new system.eventhandler ( button1_click ) ; listview1.anchor = ( ( ( anchorstyles.top | anchorstyles.bottom ) | anchorstyles.left ) | anchorstyles.right ) ; listview1.gridlines = true ; listview1.location = new point ( 10 , 9 ) ; listview1.name = "listview1" ; listview1.size = new size ( 623 , 269 ) ; listview1.tabindex = 1 ; listview1.view = view.details ; this.autoscalebasesize = new size ( 6 , 14 ) ; this.clientsize = new size ( 608 , 348 ) ; this.controls.add ( listview1 ); this.controls.add ( button1 ); this.name = "form1" ; this.startposition = formstartposition.centerscreen ; this.text = "用cQ来dxml文档" ; this.resumelayout ( false ) ; } static void main ( ) { application.run ( new form1 ( ) ) ; } private void button1_click ( object sender , system.eventargs e ) { listviewitem myitem = new listviewitem ( ) ; // 构徏listviewlg listview1.columns.clear ( ) ; listview1.items.clear ( ) ; listview1.columns.add ( "name" , 80 , horizontalalignment.left ) ; listview1.columns.add ( "zip" , 80 , horizontalalignment.left ) ; listview1.columns.add ( "address" , 80 , horizontalalignment.left ) ; listview1.columns.add ( "city" , 80 , horizontalalignment.left ) ; listview1.columns.add ( "state" , 80 , horizontalalignment.left ) ; xmlnodereader reader = null ; try { string s = "" ; xmldocument doc = new xmldocument ( ) ; // 装入指定的xml文档 doc.load ( "c:\\data.xml" ) ; // 讑֮xmlnodereader对象来打开xml文g reader = new xmlnodereader ( doc ) ; // dxml文g中的数据Qƈ昄出来 while ( reader.read ( ) ) { //判断当前d得节点类?br />switch ( reader.nodetype ) { case xmlnodetype.element : s = reader.name ; break ; case xmlnodetype.text : if ( s.equals ( "name" ) ) myitem = listview1.items.add ( reader.value ) ; else myitem.subitems.add ( reader.value ) ; break ; } } } finally { //清除打开的数据流 if ( reader != null ) reader.close ( ) ; } } } |
五.ȝQ?/font>
cQ和xml的渊源是很深的,本文只是从一个侧面反映了二者关pȝ密切E度。在.net framework sdk中存在许多可以直接操作xml的类库,掌握q些cd的用方法,对用cQ开发和xml相关E序是十分必要的。?/font>