备注:类型推断只适用于泛型方法,不适用于泛型类型。
以上是对泛型方法的相关概念和约束做了简单的解析,接下来看一下.NET中一些发行方法的具体实现:
/// <summary>
/// 封装一个方法,该方法具有四个参数并且不返回值。
/// </summary>
/// <param name="arg1">此委托封装的方法的第一个参数。</param><param name="arg2">此委托封装的方法的第二个参数。</param><param name="arg3">此委托封装的方法的第三个参数。</param><param name="arg4">此委托封装的方法的第四个参数。</param><typeparam name="T1">此委托封装的方法的第一个参数类型。</typeparam><typeparam name="T2">此委托封装的方法的第二个参数类型。</typeparam><typeparam name="T3">此委托封装的方法的第三个参数类型。</typeparam><typeparam name="T4">此委托封装的方法的第四个参数类型。</typeparam><filterpriority>2</filterpriority>
[TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
[__DynamicallyInvokable]
public delegate void Action<in T1, in T2, in T3, in T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
/// <summary>
/// 表示比较同一类型的两个对象的方法。
/// </summary>
///
/// <returns>
/// 一个有符号整数,指示 <paramref name="x"/> 与 <paramref name="y"/> 的相对值,如下表所示。 值 含义 小于 0 <paramref name="x"/> 小于 <paramref name="y"/>。 0 <paramref name="x"/> 等于 <paramref name="y"/>。 大于 0 <paramref name="x"/> 大于 <paramref name="y"/>。
/// </returns>
/// <param name="x">要比较的第一个对象。</param><param name="y">要比较的第二个对象。</param><typeparam name="T">要比较的对象的类型。</typeparam><filterpriority>1</filterpriority>
[__DynamicallyInvokable]
public delegate int Comparison<in T>(T x, T y);
四.泛型方法应用代码示例:
以上讲解的有关泛型方法的内容,这里提供一个有关泛型方法操作XML的代码:
/// <summary>
/// 泛型方法:编译器能够根据传入的方法参数推断类型参数;它无法仅从约束或返回值推断类型参数
/// </summary>
public class ObjectXmlSerializer
{
/// <summary>
/// 文件的反序列化
/// </summary>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="fileName"></param>
/// <returns>
/// 如果日志启用,则发生异常时,异常写入日志,若日志没有开启,则直接抛出异常信息
/// loggingEnabled==true: Null is returned if any error occurs.
/// loggingEnabled==false: throw exception
/// </returns>
public static T LoadFromXml<T>(string fileName) where T : class
{
return LoadFromXml<T>(fileName, true);
}
/// <summary>
/// 文件反序列化,若发生异常,异常信息写入日志
/// </summary>
/// <typeparam name="T">加载类的类型</typeparam>
/// <param name="fileName">文件名字</param>
/// <param name="loggingEnabled">启用日志记录</param>
/// <returns></returns>
public static T LoadFromXml<T>(string fileName, bool loggingEnabled) where T : class
{
FileStream fs = null;
try
{
var serializer = new XmlSerializer(typeof(T));
fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
//反序列化对象
return (T)serializer.Deserialize(fs);
}
catch (Exception e)
{
if (loggingEnabled)
{
//文件异常,写入日志
LogLoadFileException(fileName, e);
return null;
}
else
{
throw new Exception(e.Message);
}
}
finally
{
if (fs != null) fs.Close();
}
}
/// <summary>
/// 序列化一个对象到文件中.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName">文件名</param>
/// <param name="data">待序列化的数据</param>
/// <returns>
/// 如果日志启用,则发生异常时,异常写入日志,若日志没有开启,则直接抛出异常信息
/// loggingEnabled==true: log exception
/// loggingEnabled==false: throw exception
/// </returns>
public static void SaveToXml<T>(string fileName, T data) where T : class
{
SaveToXml(fileName, data, true);
}
/// <summary>
/// 文件反序列化,若发生异常,异常信息写入日志
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="fileName">文件名</param>
/// <param name="data">发序列化对象</param>
/// <param name="loggingEnabled">是否启用日志</param>
public static void SaveToXml<T>(string fileName, T data, bool loggingEnabled) where T : class
{
FileStream fs = null;
try
{
var serializer = new XmlSerializer(typeof(T));
fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
//序列化对象
serializer.Serialize(fs, data);
}
catch (Exception e)
{
if (loggingEnabled) LogSaveFileException(fileName, e);
else
{
throw new Exception(e.Message);
}
}
finally
{
if (fs != null) fs.Close();
}
}
/// <summary>
/// 序列化
/// XML & Datacontract Serialize & Deserialize Helper
/// </summary>
/// <typeparam name="T">T指定必须为class类型</typeparam>
/// <param name="serialObject"></param>
/// <returns></returns>
public static string XmlSerializer<T>(T serialObject) where T : class
{
var ser = new XmlSerializer(typeof(T));
//MemoryStream实现对内存的读写,而不是对持久性存储器进行读写
//MemoryStream封装以无符号字节数组形式存储的数据,该数组在创建MemoryStream对象时被初始化,
//或者该数组可创建为空数组。可在内存中直接访问这些封装的数据。
//内存流可降低应用程序中对临时缓冲区和临时文件的需要。
var mem = new MemoryStream();
var writer = new XmlTextWriter(mem, UTF8);
ser.Serialize(writer, serialObject);
writer.Close();
return UTF8.GetString(mem.ToArray());
}
/// <summary>
/// 反序列化
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <returns></returns>
public static T XmlDeserialize<T>(string str) where T : class
{
var mySerializer = new XmlSerializer(typeof(T));
var mem2 = new StreamReader(new MemoryStream(UTF8.GetBytes(str)), UTF8);
return (T)mySerializer.Deserialize(mem2);
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="xmlData"></param>
/// <returns>返回值类型为传入的类型</returns>
public static T DataContractDeserializer<T>(string xmlData) where T : class
{
var stream = new MemoryStream(UTF8.GetBytes(xmlData));
var reader = XmlDictionaryReader.CreateTextReader(stream, new XmlDictionaryReaderQuotas());
var ser = new DataContractSerializer(typeof(T));
var deserializedPerson = (T)ser.ReadObject(reader, true);
reader.Close();
stream.Close();
return deserializedPerson;
}
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="myObject"></param>
/// <returns></returns>
public static string DataContractSerializer<T>(T myObject) where T : class
{
var stream = new MemoryStream();
var ser = new DataContractSerializer(typeof(T));
ser.WriteObject(stream, myObject);
stream.Close();
return UTF8.GetString(stream.ToArray());
}
/// <summary>
/// 序列化时异常日志
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="ex">异常</param>
[Conditional("TRACE")]
private static void LogLoadFileException(string fileName, Exception ex)
{
var sb = new StringBuilder();
sb.Append("Fail to load xml file: ");
sb.Append(fileName + Environment.NewLine);
sb.Append(ex);
//写入日志记录中方法
// Logger.LogEvent(LogCategory, LogEventLoadFileException, sb.ToString());
}
/// <summary>
/// 反序列化时异常日志
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="ex">异常</param>
[Conditional("TRACE")]
private static void LogSaveFileException(string fileName, Exception ex)
{
var sb = new StringBuilder();
sb.Append("Fail to save xml file: ");
sb.Append(fileName + Environment.NewLine);
sb.Append(ex);
}
/// <summary>
/// 将xml字符串序列化为数据流(数据流编码为ASCII,UTF8)
/// </summary>
/// <returns>字符串转换到流</returns>
public static MemoryStream StringXmlToStream(string strXml,Encoding encod)
{
MemoryStream memoryStream = null;
try
{
Encoding encoding;
if (Equals(encod, ASCII))
{
encoding = new ASCIIEncoding();
}
else
{
encoding = new UTF8Encoding();
}
var byteArray = encoding.GetBytes(strXml);
memoryStream = new MemoryStream(byteArray);
memoryStream.Seek(0, SeekOrigin.Begin);
return memoryStream;
}
catch (IOException ex)
{
throw new IOException(ex.Message);
}
finally
{
if (memoryStream != null) memoryStream.Close();
}
}
}










