C#常用功能函数小结(.NET 4.5)
今天有空,把C#常用的功能总结一下,希望对您有用。(适用于.NET Framework 4.5)
1. 把类转换为字符串(序列化为XML字符串,支持xml的namespace)
using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; public static string Serialize<T>(T t, string nameSpacePri, string nameSpace) { try { var myNamespaces = new XmlSerializerNamespaces(); myNamespaces.Add(nameSpacePri, nameSpace); var xs = new XmlSerializer(t.GetType()); using (var memoryStream = new MemoryStream()) { var settings = new XmlWriterSettings() { Encoding = Encoding.UTF8 }; using (var writer = XmlWriter.Create(memoryStream, settings)) { xs.Serialize(writer, t, myNamespaces); } return Encoding.UTF8.GetString(memoryStream.ToArray()); } } catch (System.Exception) { return null; } }
2. 把带namespace的XML字符串反序列化为类对象
using System.IO; using System.Text; using System.Xml; using System.Xml.Serialization; public sealed class XmlSerilizer { public static T Deserialize<T>(string input) { try { var xs = new XmlSerializer(typeof (T)); using (var reader = new StringReader(input)) { var namespaceReader = new NamespaceIgnorantXmlTextReader(reader); return (T) xs.Deserialize(namespaceReader); } } catch (System.Exception e) { return default(T); } } } //忽略xml里面的namespace public class NamespaceIgnorantXmlTextReader : XmlTextReader { /// <summary> /// Initializes a new instance of the <see cref="NamespaceIgnorantXmlTextReader"/> class. /// </summary> /// <param name="reader">The reader.</param> public NamespaceIgnorantXmlTextReader(System.IO.TextReader reader) : base(reader) { } /// <summary> /// Gets the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned. /// </summary> /// <value>The namespace URI.</value> /// <returns>The namespace URI of the current node; otherwise an empty string.</returns> public override string NamespaceURI { get { return ""; } } }
以上要注意xml的root,实体类要这样写:
[Serializable] [XmlRoot(ElementName = "yourXmlRootName", DataType = "string", IsNullable = true)] public class Model { [XmlElement(ElementName = "merchant", IsNullable = true)] public string merchant { get; set; } [XmlElement(ElementName = "address", IsNullable = false)] public string address{ get; set; } [XmlElement(ElementName = "status", IsNullable = false)] public string status { get; set; } }
3. 把JSON字符串反序列化为类对象
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonString);
4. 把类对象序列化为字符串
string output = Newtonsoft.Json.JsonConvert.SerializeObject(product);
5. 获取程序的App data path
using System.Text; using System.Threading; using System.Threading.Tasks; using System; using System.IO; using System.Reflection; using System.Security.Cryptography; public static string GetApplicationDataPath() { try { var asm = Assembly.GetEntryAssembly(); var attrs = asm.GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); var company = (AssemblyCompanyAttribute)attrs[0]; attrs = asm.GetCustomAttributes(typeof(AssemblyTrademarkAttribute), false); var tradeMark = (AssemblyTrademarkAttribute)attrs[0]; var pathTemp = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), company.Company); pathTemp = Path.Combine(pathTemp, tradeMark.Trademark); pathTemp = Path.Combine(pathTemp, asm.GetName().Name); return pathTemp; } catch (System.Exception) { return string.Empty; } }
6. 清空目录(扩展方法)
using System.Text; using System.Threading; using System.Threading.Tasks; using System; using System.IO; using System.Reflection; using System.Security.Cryptography; public static void Empty(this DirectoryInfo directory) { foreach (FileInfo file in directory.GetFiles()) file.Delete(); foreach (DirectoryInfo subDirectory in directory.GetDirectories()) subDirectory.Delete(true); }
7. 计算文件的SHA1值
using System.Security.Cryptography; public static string CalculateFileSha(byte[] buffer) { using (var cryptoProvider = new SHA1CryptoServiceProvider()) { return Convert.ToBase64String(cryptoProvider.ComputeHash(buffer)); } }
8. 写文件(另一个线程)
using System.Text; using System.Threading; using System.Threading.Tasks; using System; using System.IO; using System.Reflection; using System.Security.Cryptography; public static void WriteFileAsync(string content, string fileName, bool append) { if (String.IsNullOrEmpty(content)||string.IsNullOrEmpty(fileName)) return; Task.Factory.StartNew(() => { try { using (var writer = new StreamWriter(fileName, append, Encoding.UTF8)) { writer.AutoFlush = true; writer.WriteLine(content); writer.Close(); } } catch (System.Exception) { } }); }
9. 等待被其它进程占用的文件
public static void WaitForFile(string fullPath) { while (true) { try { using (var stream = new StreamReader(fullPath)) { break; } } catch { Thread.Sleep(100); } } }
10. XmlDocument和XDocument工具类
using System.Linq; using System.Xml; using System.Xml.Linq; namespace myCompany { public sealed class XmlUtility { public static XDocument DocumentToXDocument(XmlDocument doc) { return XDocument.Load(new XmlNodeReader(doc)); } public static XmlDocument XDocumentToXmlDocument(XDocument doc) { var xmlDocument = new XmlDocument(); using (var xmlReader = doc.CreateReader()) { xmlDocument.Load(xmlReader); } return xmlDocument; } public static XDocument XElementToXDocument(XElement element) { return new XDocument(element); } public static string RemoveAllNamespaces(string xmlDocument) { XElement xmlDocumentWithoutNs = RemoveAllNamespaces(XElement.Parse(xmlDocument)); return xmlDocumentWithoutNs.ToString(); } public static XElement RemoveAllNamespaces(XElement xmlDocument) { if (!xmlDocument.HasElements) { var xElement = new XElement(xmlDocument.Name.LocalName); xElement.Value = xmlDocument.Value; foreach (var attribute in xmlDocument.Attributes()) xElement.Add(attribute); return xElement; } return new XElement(xmlDocument.Name.LocalName, xmlDocument.Elements().Select(el => RemoveAllNamespaces(el))); } public static XDocument RemoveNamespaces(XDocument xmlDocument, string namespaces) { return XDocument.Parse(xmlDocument.ToString().Replace(namespaces, "")); } } }
11. 使用XSLT转换两个xml
using System; using System.Xml.Linq; using System.Xml.Xsl; using ETMS.MCC.Logging; using ETMS.MCC.Utility; namespace myCompany { public class Converter { [ThreadStatic] private static XslCompiledTransform xslTransformer; public XDocument XsltTransform(XDocument inputDocument) { System.IO.Directory.SetCurrentDirectory(AppDomain.CurrentDomain.BaseDirectory); return Transform(Utility.Constants.Configuration.ParameterXsltFile, inputDocument); } public XDocument XsltTransform(string xsltFilename, XDocument inputDocument) { return Transform(xsltFilename, inputDocument); } private XDocument Transform(string xsltFilename, XDocument inputDocument) { try { if (xslTransformer == null) { xslTransformer = new XslCompiledTransform(); xslTransformer.Load(xsltFilename); } var result = new XDocument(); using (var xw = result.CreateWriter()) { xslTransformer.Transform(XmlUtility.XDocumentToXmlDocument(inputDocument), null, xw); xw.Close(); return result; } } catch (Exception e) { return null; } } } }
12. 批量任务处理,限制并发数
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; public static async Task BulkExecute<T>(int maxConcurrency, IEnumerable<T> items, Func<T, Task> createTask) { using (var sem = new SemaphoreSlim(maxConcurrency)) { var tasks = new List<Task>(); foreach (var item in items) { await sem.WaitAsync(); var task = createTask(item).ContinueWith(t => sem.Release()); tasks.Add(task); } await Task.WhenAll(tasks); } }
13. 支持超时时间和最大容量的同步队列
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Timers; namespace myCompany { public abstract class AbstractProcessingQueue<T> : ConcurrentQueue<T> where T : class { protected int _numberLimit; protected int _timeLimit; protected System.Timers.Timer _timer; protected int _onPublishExecuted; protected ReaderWriterLockSlim _locker; protected AbstractProcessingQueue() { } protected AbstractProcessingQueue(int numberLimit, int timeLimit) { Init(numberLimit, timeLimit); } public event Action<List<T>> OnPublish = delegate { }; public virtual new void Enqueue(T item) { base.Enqueue(item); if (_numberLimit > 0 && Count >= _numberLimit) { Logger.GlobalWrite(string.Format("Processing queue number limit: {0}", _numberLimit), LogMessageCategory.Warning); Publish(); } } private void Init(int capLimit, int timeLimit) { _numberLimit = capLimit; _timeLimit = timeLimit; _locker = new ReaderWriterLockSlim(); InitTimer(); } protected virtual void InitTimer() { if (_timeLimit < 0) return; _timer = new System.Timers.Timer {AutoReset = false, Interval = _timeLimit*1000}; _timer.Elapsed += new ElapsedEventHandler((s, e) => { Logger.GlobalWrite(string.Format("Processing queue time limit: {0}", _timeLimit), LogMessageCategory.Warning); Publish(); }); _timer.Start(); } protected virtual void Publish() { var task = new Task(() => { var itemsToLog = new List<T>(); try { if (IsPublishing()) return; StartPublishing(); T item; while (TryDequeue(out item)) { itemsToLog.Add(item); } } catch (ThreadAbortException tex) { } catch (Exception ex) { } finally { OnPublish(itemsToLog); CompletePublishing(); } }); task.Start(); } private bool IsPublishing() { return (Interlocked.CompareExchange(ref _onPublishExecuted, 1, 0) > 0); } private void StartPublishing() { if (_timer != null) _timer.Stop(); } private void CompletePublishing() { if (_timer != null) _timer.Start(); Interlocked.Decrement(ref _onPublishExecuted); } } }
14. 单例模式
using System; namespace myCompany { public sealed class Singleton { static readonly Singleton Instance = new Singleton(); private Singleton() { } public static Singleton GetInstance() { return Instance; } } }
15. 根据httpRequest和httpHeader里面的content-type,获得请求类型
using System; using System.Web; public static MediaTypes GetMediaType(string contentTypeHeader) { if (String.IsNullOrEmpty(contentTypeHeader)) return MediaTypes.UNKNOWN; if (contentTypeHeader.Contains("text/plain")) return MediaTypes.TEXT; if (contentTypeHeader.Contains("application/json")) return MediaTypes.JSON; if (contentTypeHeader.Contains("html")) return MediaTypes.HTML; if (contentTypeHeader.Contains("application/xml")) return MediaTypes.XML; return MediaTypes.UNKNOWN; }
16. 解析URL的parameter,例如http://www.abc.com?a=1&b=2&c=3,获取a,b,c
using System; using System.Web; public static string ParseText(string bodyText, string key) { var myUri = new Uri("http://www.vefifone.com?" + bodyText); return HttpUtility.ParseQueryString(myUri.Query).Get(key); }
17. 解析xml字符串,获取其中一个字段的值
using System.Xml; using System.Xml.Linq; public long ParseXmlString(string messageBody) { try { var xm = new XmlDocument(); xm.LoadXml(messageBody); using (var reader = new XmlNodeReader(xm)) { var Id = ""; var doc = XDocument.Load(reader); var ele = doc.Document.Element("root1").Element("elementName"); if (ele != null) Id = ele.Value; long id; if (!Int64.TryParse(Id, out id)) { return -1; } return id; } } catch (Exception e) { return -1; } }
18. 把多个文件内容byte[]压缩为一个zip包,返回字节流byte[]
using ICSharpCode.SharpZipLib.Core; using ICSharpCode.SharpZipLib.Zip; using System.IO; public byte[] ZipFiles(IEnumerable<byte[]> contents) { try { using (var compressedFileStream = new MemoryStream()) { using (var zipStream = new ZipOutputStream(compressedFileStream)) { zipStream.SetLevel(9); foreach (var p in contents) { using (var srcStream = new MemoryStream(p)) { var entry = new ZipEntry("newname"); zipStream.PutNextEntry(entry); StreamUtils.Copy(srcStream, zipStream, new byte[4096]); zipStream.CloseEntry(); } } zipStream.IsStreamOwner = false; zipStream.Close(); compressedFileStream.Position = 0; return compressedFileStream.ToArray(); } } } catch (Exception e) { return null; } }
19. 反序列化JsonDeserializer, XmlJsonDeserializer, DotNetXmlJsonDeserializer
interface IsonDeserializer:
namespace myCompany { public interface IDeserializer { T Deserialize<T>(IRestResponse response); string RootElement { get; set; } string Namespace { get; set; } string DateFormat { get; set; } } }
JsonDeserializer:
using System; using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; using RestSharp.Extensions; namespace myCompany { public class JsonDeserializer : IDeserializer { public string RootElement { get; set; } public string Namespace { get; set; } public string DateFormat { get; set; } public CultureInfo Culture { get; set; } public JsonDeserializer() { Culture = CultureInfo.InvariantCulture; } public T Deserialize<T>(IRestResponse response) { var target = Activator.CreateInstance<T>(); if (target is IList) { var objType = target.GetType(); if (RootElement.HasValue()) { var root = FindRoot(response.Content); target = (T)BuildList(objType, root); } else { var data = SimpleJson.DeserializeObject(response.Content); target = (T)BuildList(objType, data); } } else if (target is IDictionary) { var root = FindRoot(response.Content); target = (T)BuildDictionary(target.GetType(), root); } else { var root = FindRoot(response.Content); Map(target, (IDictionary<string, object>)root); } return target; } private object FindRoot(string content) { var data = (IDictionary<string, object>)SimpleJson.DeserializeObject(content); if (RootElement.HasValue() && data.ContainsKey(RootElement)) { return data[RootElement]; } return data; } private void Map(object target, IDictionary<string, object> data) { var objType = target.GetType(); var props = objType.GetProperties().Where(p => p.CanWrite).ToList(); foreach (var prop in props) { var type = prop.PropertyType; string name = String.Empty; var attributes = prop.GetCustomAttributes(typeof(DeserializeAsAttribute), false); if (attributes.Length > 0) { var attribute = (DeserializeAsAttribute)attributes[0]; name = attribute.Name; } else { name = prop.Name; } var actualName = name.GetNameVariants(Culture).FirstOrDefault(n => data.ContainsKey(n)); var value = actualName != null ? data[actualName] : null; if (value == null) continue; prop.SetValue(target, ConvertValue(type, value), null); } } private IDictionary BuildDictionary(Type type, object parent) { var dict = (IDictionary)Activator.CreateInstance(type); var valueType = type.GetGenericArguments()[1]; foreach (var child in (IDictionary<string, object>)parent) { var key = child.Key; object item = null; if (valueType.IsGenericType && valueType.GetGenericTypeDefinition() == typeof(List<>)) { item = BuildList(valueType, child.Value); } else { item = ConvertValue(valueType, child.Value); } dict.Add(key, item); } return dict; } private IList BuildList(Type type, object parent) { var list = (IList)Activator.CreateInstance(type); var listType = type.GetInterfaces().First(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IList<>)); var itemType = listType.GetGenericArguments()[0]; if (parent is IList) { foreach (var element in (IList)parent) { if (itemType.IsPrimitive) { var value = element.ToString(); list.Add(value.ChangeType(itemType, Culture)); } else if (itemType == typeof(string)) { if (element == null) { list.Add(null); continue; } list.Add(element.ToString()); } else { if (element == null) { list.Add(null); continue; } var item = ConvertValue(itemType, element); list.Add(item); } } } else { list.Add(ConvertValue(itemType, parent)); } return list; } private object ConvertValue(Type type, object value) { var stringValue = Convert.ToString(value, Culture); // check for nullable and extract underlying type if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { // Since the type is nullable and no value is provided return null if (String.IsNullOrEmpty(stringValue)) return null; type = type.GetGenericArguments()[0]; } if (type == typeof(System.Object) && value != null) { type = value.GetType(); } if (type.IsPrimitive) { return value.ChangeType(type, Culture); } else if (type.IsEnum) { return type.FindEnumValue(stringValue, Culture); } else if (type == typeof(Uri)) { return new Uri(stringValue, UriKind.RelativeOrAbsolute); } else if (type == typeof(string)) { return stringValue; } else if (type == typeof(DateTime) #if !PocketPC || type == typeof(DateTimeOffset) #endif ) { DateTime dt; if (DateFormat.HasValue()) { dt = DateTime.ParseExact(stringValue, DateFormat, Culture); } else { // try parsing instead dt = stringValue.ParseJsonDate(Culture); } #if PocketPC return dt; #else if (type == typeof(DateTime)) { return dt; } else if (type == typeof(DateTimeOffset)) { return (DateTimeOffset)dt; } #endif } else if (type == typeof(Decimal)) { if (value is double) return (decimal)((double)value); return Decimal.Parse(stringValue, Culture); } else if (type == typeof(Guid)) { return string.IsNullOrEmpty(stringValue) ? Guid.Empty : new Guid(stringValue); } else if (type == typeof(TimeSpan)) { return TimeSpan.Parse(stringValue); } else if (type.IsGenericType) { var genericTypeDef = type.GetGenericTypeDefinition(); if (genericTypeDef == typeof(List<>)) { return BuildList(type, value); } else if (genericTypeDef == typeof(Dictionary<,>)) { var keyType = type.GetGenericArguments()[0]; // only supports Dict<string, T>() if (keyType == typeof(string)) { return BuildDictionary(type, value); } } else { // nested property classes return CreateAndMap(type, value); } } else { // nested property classes return CreateAndMap(type, value); } return null; } private object CreateAndMap(Type type, object element) { var instance = Activator.CreateInstance(type); Map(instance, (IDictionary<string, object>)element); return instance; } } }
XmlDeserializer:
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Xml.Linq; using RestSharp.Extensions; using System.Globalization; using System.Xml; using System.ComponentModel; namespace myCompany { public class XmlDeserializer : IDeserializer { public string RootElement { get; set; } public string Namespace { get; set; } public string DateFormat { get; set; } public CultureInfo Culture { get; set; } public XmlDeserializer() { Culture = CultureInfo.InvariantCulture; } public virtual T Deserialize<T>(IRestResponse response) { if (string.IsNullOrEmpty( response.Content )) return default(T); var doc = XDocument.Parse(response.Content); var root = doc.Root; if (RootElement.HasValue() && doc.Root != null) { root = doc.Root.Element(RootElement.AsNamespaced(Namespace)); } // autodetect xml namespace if (!Namespace.HasValue()) { RemoveNamespace(doc); } var x = Activator.CreateInstance<T>(); var objType = x.GetType(); if (objType.IsSubclassOfRawGeneric(typeof(List<>))) { x = (T)HandleListDerivative(x, root, objType.Name, objType); } else { Map(x, root); } return x; } private void RemoveNamespace(XDocument xdoc) { foreach (XElement e in xdoc.Root.DescendantsAndSelf()) { if (e.Name.Namespace != XNamespace.None) { e.Name = XNamespace.None.GetName(e.Name.LocalName); } if (e.Attributes().Any(a => a.IsNamespaceDeclaration || a.Name.Namespace != XNamespace.None)) { e.ReplaceAttributes(e.Attributes().Select(a => a.IsNamespaceDeclaration ? null : a.Name.Namespace != XNamespace.None ? new XAttribute(XNamespace.None.GetName(a.Name.LocalName), a.Value) : a)); } } } protected virtual void Map(object x, XElement root) { var objType = x.GetType(); var props = objType.GetProperties(); foreach (var prop in props) { var type = prop.PropertyType; if (!type.IsPublic || !prop.CanWrite) continue; var name = prop.Name.AsNamespaced(Namespace); var value = GetValueFromXml(root, name, prop); if (value == null) { // special case for inline list items if (type.IsGenericType) { var genericType = type.GetGenericArguments()[0]; var first = GetElementByName(root, genericType.Name); var list = (IList)Activator.CreateInstance(type); if (first != null) { var elements = root.Elements(first.Name); PopulateListFromElements(genericType, elements, list); } prop.SetValue(x, list, null); } continue; } // check for nullable and extract underlying type if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) { // if the value is empty, set the property to null... if (value == null || String.IsNullOrEmpty(value.ToString())) { prop.SetValue(x, null, null); continue; } type = type.GetGenericArguments()[0]; } if (type == typeof(bool)) { var toConvert = value.ToString().ToLower(); prop.SetValue(x, XmlConvert.ToBoolean(toConvert), null); } else if (type.IsPrimitive) { prop.SetValue(x, value.ChangeType(type, Culture), null); } else if (type.IsEnum) { var converted = type.FindEnumValue(value.ToString(), Culture); prop.SetValue(x, converted, null); } else if (type == typeof(Uri)) { var uri = new Uri(value.ToString(), UriKind.RelativeOrAbsolute); prop.SetValue(x, uri, null); } else if (type == typeof(string)) { prop.SetValue(x, value, null); } else if (type == typeof(DateTime)) { if (DateFormat.HasValue()) { value = DateTime.ParseExact(value.ToString(), DateFormat, Culture); } else { value = DateTime.Parse(value.ToString(), Culture); } prop.SetValue(x, value, null); } #if !PocketPC else if (type == typeof(DateTimeOffset)) { var toConvert = value.ToString(); if (!string.IsNullOrEmpty(toConvert)) { DateTimeOffset deserialisedValue; try { deserialisedValue = XmlConvert.ToDateTimeOffset(toConvert); prop.SetValue(x, deserialisedValue, null); } catch (Exception) { object result; if (TryGetFromString(toConvert, out result, type)) { prop.SetValue(x, result, null); } else { //fallback to parse deserialisedValue = DateTimeOffset.Parse(toConvert); prop.SetValue(x, deserialisedValue, null); } } } } #endif else if (type == typeof(Decimal)) { value = Decimal.Parse(value.ToString(), Culture); prop.SetValue(x, value, null); } else if (type == typeof(Guid)) { var raw = value.ToString(); value = string.IsNullOrEmpty(raw) ? Guid.Empty : new Guid(value.ToString()); prop.SetValue(x, value, null); } else if (type == typeof(TimeSpan)) { var timeSpan = XmlConvert.ToTimeSpan(value.ToString()); prop.SetValue(x, timeSpan, null); } else if (type.IsGenericType) { var t = type.GetGenericArguments()[0]; var list = (IList)Activator.CreateInstance(type); var container = GetElementByName(root, prop.Name.AsNamespaced(Namespace)); if (container.HasElements) { var first = container.Elements().FirstOrDefault(); var elements = container.Elements(first.Name); PopulateListFromElements(t, elements, list); } prop.SetValue(x, list, null); } else if (type.IsSubclassOfRawGeneric(typeof(List<>))) { // handles classes that derive from List<T> // e.g. a collection that also has attributes var list = HandleListDerivative(x, root, prop.Name, type); prop.SetValue(x, list, null); } else { //fallback to type converters if possible object result; if (TryGetFromString(value.ToString(), out result, type)) { prop.SetValue(x, result, null); } else { // nested property classes if (root != null) { var element = GetElementByName(root, name); if (element != null) { var item = CreateAndMap(type, element); prop.SetValue(x, item, null); } } } } } } private static bool TryGetFromString(string inputString, out object result, Type type) { #if !SILVERLIGHT && !WINDOWS_PHONE && !PocketPC var converter = TypeDescriptor.GetConverter(type); if (converter.CanConvertFrom(typeof(string))) { result = (converter.ConvertFromInvariantString(inputString)); return true; } result = null; return false; #else result = null; return false; #endif } private void PopulateListFromElements(Type t, IEnumerable<XElement> elements, IList list) { foreach (var element in elements) { var item = CreateAndMap(t, element); list.Add(item); } } private object HandleListDerivative(object x, XElement root, string propName, Type type) { Type t; if (type.IsGenericType) { t = type.GetGenericArguments()[0]; } else { t = type.BaseType.GetGenericArguments()[0]; } var list = (IList)Activator.CreateInstance(type); var elements = root.Descendants(t.Name.AsNamespaced(Namespace)); var name = t.Name; if (!elements.Any()) { var lowerName = name.ToLower().AsNamespaced(Namespace); elements = root.Descendants(lowerName); } if (!elements.Any()) { var camelName = name.ToCamelCase(Culture).AsNamespaced(Namespace); elements = root.Descendants(camelName); } if (!elements.Any()) { elements = root.Descendants().Where(e => e.Name.LocalName.RemoveUnderscoresAndDashes() == name); } if (!elements.Any()) { var lowerName = name.ToLower().AsNamespaced(Namespace); elements = root.Descendants().Where(e => e.Name.LocalName.RemoveUnderscoresAndDashes() == lowerName); } PopulateListFromElements(t, elements, list); // get properties too, not just list items // only if this isn't a generic type if (!type.IsGenericType) { Map(list, root.Element(propName.AsNamespaced(Namespace)) ?? root); // when using RootElement, the heirarchy is different } return list; } protected virtual object CreateAndMap(Type t, XElement element) { object item; if (t == typeof(String)) { item = element.Value; } else if (t.IsPrimitive) { item = element.Value.ChangeType(t, Culture); } else { item = Activator.CreateInstance(t); Map(item, element); } return item; } protected virtual object GetValueFromXml(XElement root, XName name, PropertyInfo prop) { object val = null; if (root != null) { var element = GetElementByName(root, name); if (element == null) { var attribute = GetAttributeByName(root, name); if (attribute != null) { val = attribute.Value; } } else { if (!element.IsEmpty || element.HasElements || element.HasAttributes) { val = element.Value; } } } return val; } protected virtual XElement GetElementByName(XElement root, XName name) { var lowerName = name.LocalName.ToLower().AsNamespaced(name.NamespaceName); var camelName = name.LocalName.ToCamelCase(Culture).AsNamespaced(name.NamespaceName); if (root.Element(name) != null) { return root.Element(name); } if (root.Element(lowerName) != null) { return root.Element(lowerName); } if (root.Element(camelName) != null) { return root.Element(camelName); } if (name == "Value".AsNamespaced(name.NamespaceName)) { return root; } // try looking for element that matches sanitized property name (Order by depth) var element = root.Descendants() .OrderBy(d => d.Ancestors().Count()) .FirstOrDefault(d => d.Name.LocalName.RemoveUnderscoresAndDashes() == name.LocalName) ?? root.Descendants() .OrderBy(d => d.Ancestors().Count()) .FirstOrDefault(d => d.Name.LocalName.RemoveUnderscoresAndDashes() == name.LocalName.ToLower()); if (element != null) { return element; } return null; } protected virtual XAttribute GetAttributeByName(XElement root, XName name) { var lowerName = name.LocalName.ToLower().AsNamespaced(name.NamespaceName); var camelName = name.LocalName.ToCamelCase(Culture).AsNamespaced(name.NamespaceName); if (root.Attribute(name) != null) { return root.Attribute(name); } if (root.Attribute(lowerName) != null) { return root.Attribute(lowerName); } if (root.Attribute(camelName) != null) { return root.Attribute(camelName); } // try looking for element that matches sanitized property name var element = root.Attributes().FirstOrDefault(d => d.Name.LocalName.RemoveUnderscoresAndDashes() == name.LocalName); if (element != null) { return element; } return null; } } }
DotNetXmlDeserializer:
using System.IO; using System.Text; namespace myCompany { public class DotNetXmlDeserializer : IDeserializer { public string DateFormat { get; set; } public string Namespace { get; set; } public string RootElement { get; set; } public T Deserialize<T>(IRestResponse response) { if (string.IsNullOrEmpty(response.Content)) { return default(T); } using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(response.Content))) { var serializer = new System.Xml.Serialization.XmlSerializer(typeof(T)); return (T)serializer.Deserialize(stream); } } } }
20. 常用扩展方法(持续更新)
using System.IO; using System.Text; namespace myCompany.Helper { /* * 与Stream和byte[]有关的扩展方法 */ public static class DataExtensions { /* * 把字符串用UTF8流Stream输出 * 用法: context.Response.OutputStream.WriteStringUtf8( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <Response> <Error> <Message>Not found!</Message> </Error> </Response>"); */ public static void WriteStringUtf8(this Stream target, string value) { var encoded = Encoding.UTF8.GetBytes(value); target.Write(encoded, 0, encoded.Length); } //把字节流byte[]另存为文件 public static void SaveAs(this byte[] input, string path) { File.WriteAllBytes(path, input); } //流Stream读为 byte[] public static byte[] ReadAsBytes(this Stream input) { byte[] buffer = new byte[16 * 1024]; using (MemoryStream ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } //Stream CopyTo方法 public static void CopyTo(this Stream input, Stream output) { var buffer = new byte[32768]; while(true) { var read = input.Read(buffer, 0, buffer.Length); if(read <= 0) return; output.Write(buffer, 0, read); } } //byte[]转换为字符串 public static string AsString(this byte[] buffer) { if (buffer == null) return ""; // Ansi as default Encoding encoding = Encoding.UTF8; return encoding.GetString(buffer, 0, buffer.Length); } } /* * 与反射/Reflection有关的扩展方法 */ public static class ReflectionExtensions { /// <summary> /// Retrieve an attribute from a member (property) /// </summary> /// <typeparam name="T">Type of attribute to retrieve</typeparam> /// <param name="prop">Member to retrieve attribute from</param> /// <returns></returns> public static T GetAttribute<T>(this MemberInfo prop) where T : Attribute { return Attribute.GetCustomAttribute(prop, typeof(T)) as T; } /// <summary> /// Retrieve an attribute from a type /// </summary> /// <typeparam name="T">Type of attribute to retrieve</typeparam> /// <param name="type">Type to retrieve attribute from</param> /// <returns></returns> public static T GetAttribute<T>(this Type type) where T : Attribute { return Attribute.GetCustomAttribute(type, typeof(T)) as T; } /// <summary> /// Checks a type to see if it derives from a raw generic (e.g. List[[]]) /// </summary> /// <param name="toCheck"></param> /// <param name="generic"></param> /// <returns></returns> public static bool IsSubclassOfRawGeneric(this Type toCheck, Type generic) { while (toCheck != typeof(object)) { var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck; if (generic == cur) { return true; } toCheck = toCheck.BaseType; } return false; } public static object ChangeType(this object source, Type newType) { return Convert.ChangeType(source, newType); } public static object ChangeType(this object source, Type newType, CultureInfo culture) { return Convert.ChangeType(source, newType, culture); } /// <summary> /// Find a value from a System.Enum by trying several possible variants /// of the string value of the enum. /// </summary> /// <param name="type">Type of enum</param> /// <param name="value">Value for which to search</param> /// <param name="culture">The culture used to calculate the name variants</param> /// <returns></returns> public static object FindEnumValue(this Type type, string value, CultureInfo culture) { var ret = Enum.GetValues( type ) .Cast<Enum>() .FirstOrDefault(v => v.ToString().GetNameVariants(culture).Contains(value, StringComparer.Create(culture, true))); if (ret == null) { var enumValueAsUnderlyingType = Convert.ChangeType(value, Enum.GetUnderlyingType(type), culture); if (enumValueAsUnderlyingType != null && Enum.IsDefined(type, enumValueAsUnderlyingType)) { ret = (Enum) Enum.ToObject(type, enumValueAsUnderlyingType); } } return ret; } } /* * 与String字符串有关的扩展方法 */ public static class StringExtensions { public static bool IsNullOrBlank(this string value) { return String.IsNullOrEmpty(value) || (!String.IsNullOrEmpty(value) && value.Trim() == String.Empty); } public static bool EqualsIgnoreCase(this string left, string right) { return String.Compare(left, right, StringComparison.OrdinalIgnoreCase) == 0; } public static bool EqualsAny(this string input, params string[] args) { return args.Aggregate(false, (current, arg) => current | input.Equals(arg)); } public static string FormatWith(this string format, params object[] args) { return String.Format(format, args); } public static string FormatWithInvariantCulture(this string format, params object[] args) { return String.Format(CultureInfo.InvariantCulture, format, args); } public static string Then(this string input, string value) { return String.Concat(input, value); } public static string UrlEncode(this string value) { // [DC] This is more correct than HttpUtility; it escapes spaces as %20, not + return Uri.EscapeDataString(value); } public static string UrlDecode(this string value) { return Uri.UnescapeDataString(value); } public static Uri AsUri(this string value) { return new Uri(value); } public static string ToBase64String(this byte[] input) { return Convert.ToBase64String(input); } public static byte[] GetBytes(this string input) { return Encoding.UTF8.GetBytes(input); } public static string PercentEncode(this string s) { var bytes = s.GetBytes(); var sb = new StringBuilder(); foreach (var b in bytes) { // [DC]: Support proper encoding of special characters (\n\r\t\b) if ((b > 7 && b < 11) || b == 13) { sb.Append(string.Format("%0{0:X}", b)); } else { sb.Append(string.Format("%{0:X}", b)); } } return sb.ToString(); } public static IDictionary<string, string> ParseQueryString(this string query) { // [DC]: This method does not URL decode, and cannot handle decoded input if (query.StartsWith("?")) query = query.Substring(1); if (query.Equals(string.Empty)) { return new Dictionary<string, string>(); } var parts = query.Split(new[] {'&'}); return parts.Select( part => part.Split(new[] {'='})).ToDictionary( pair => pair[0], pair => pair[1] ); } public static string UrlDecode(this string input) { return HttpUtility.UrlDecode(input); } /// <summary> /// Uses Uri.EscapeDataString() based on recommendations on MSDN /// http://blogs.msdn.com/b/yangxind/archive/2006/11/09/don-t-use-net-system-uri-unescapedatastring-in-url-decoding.aspx /// </summary> public static string UrlEncode(this string input) { const int maxLength = 32766; if (input == null) throw new ArgumentNullException("input"); if (input.Length <= maxLength) return Uri.EscapeDataString(input); StringBuilder sb = new StringBuilder(input.Length * 2); int index = 0; while (index < input.Length) { int length = Math.Min(input.Length - index, maxLength); string subString = input.Substring(index, length); sb.Append(Uri.EscapeDataString(subString)); index += subString.Length; } return sb.ToString(); } public static string HtmlDecode(this string input) { return HttpUtility.HtmlDecode(input); } public static string HtmlEncode(this string input) { return HttpUtility.HtmlEncode(input); } public static string HtmlAttributeEncode(this string input) { return HttpUtility.HtmlAttributeEncode(input); } /// <summary> /// Check that a string is not null or empty /// </summary> /// <param name="input">String to check</param> /// <returns>bool</returns> public static bool HasValue(this string input) { return !string.IsNullOrEmpty(input); } /// <summary> /// Remove underscores from a string /// </summary> /// <param name="input">String to process</param> /// <returns>string</returns> public static string RemoveUnderscoresAndDashes(this string input) { return input.Replace("_", "").Replace("-", ""); // avoiding regex } /// <summary> /// Parses most common JSON date formats /// </summary> /// <param name="input">JSON value to parse</param> /// <returns>DateTime</returns> public static DateTime ParseJsonDate(this string input, CultureInfo culture) { input = input.Replace("\n", ""); input = input.Replace("\r", ""); input = input.RemoveSurroundingQuotes(); long? unix = null; try { unix = Int64.Parse(input); } catch (Exception) { }; if (unix.HasValue) { var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return epoch.AddSeconds(unix.Value); } if (input.Contains("/Date(")) { return ExtractDate(input, @"\\?/Date\((-?\d+)(-|\+)?([0-9]{4})?\)\\?/", culture); } if (input.Contains("new Date(")) { input = input.Replace(" ", ""); // because all whitespace is removed, match against newDate( instead of new Date( return ExtractDate(input, @"newDate\((-?\d+)*\)", culture); } return ParseFormattedDate(input, culture); } /// <summary> /// Remove leading and trailing " from a string /// </summary> /// <param name="input">String to parse</param> /// <returns>String</returns> public static string RemoveSurroundingQuotes(this string input) { if (input.StartsWith("\"") && input.EndsWith("\"")) { // remove leading/trailing quotes input = input.Substring(1, input.Length - 2); } return input; } private static DateTime ParseFormattedDate(string input, CultureInfo culture) { var formats = new[] { "u", "s", "yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", "yyyy-MM-ddTHH:mm:ssZ", "yyyy-MM-dd HH:mm:ssZ", "yyyy-MM-ddTHH:mm:ss", "yyyy-MM-ddTHH:mm:sszzzzzz", "M/d/yyyy h:mm:ss tt" // default format for invariant culture }; DateTime date; if (DateTime.TryParseExact(input, formats, culture, DateTimeStyles.None, out date)) { return date; } if (DateTime.TryParse(input, culture, DateTimeStyles.None, out date)) { return date; } return default(DateTime); } private static DateTime ExtractDate(string input, string pattern, CultureInfo culture) { DateTime dt = DateTime.MinValue; var regex = new Regex(pattern); if (regex.IsMatch(input)) { var matches = regex.Matches(input); var match = matches[0]; var ms = Convert.ToInt64(match.Groups[1].Value); var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); dt = epoch.AddMilliseconds(ms); // adjust if time zone modifier present if (match.Groups.Count > 2 && !String.IsNullOrEmpty(match.Groups[3].Value)) { var mod = DateTime.ParseExact(match.Groups[3].Value, "HHmm", culture); if (match.Groups[2].Value == "+") { dt = dt.Add(mod.TimeOfDay); } else { dt = dt.Subtract(mod.TimeOfDay); } } } return dt; } /// <summary> /// Checks a string to see if it matches a regex /// </summary> /// <param name="input">String to check</param> /// <param name="pattern">Pattern to match</param> /// <returns>bool</returns> public static bool Matches(this string input, string pattern) { return Regex.IsMatch(input, pattern); } /// <summary> /// Converts a string to pascal case /// </summary> /// <param name="lowercaseAndUnderscoredWord">String to convert</param> /// <returns>string</returns> public static string ToPascalCase(this string lowercaseAndUnderscoredWord, CultureInfo culture) { return ToPascalCase(lowercaseAndUnderscoredWord, true, culture); } /// <summary> /// Converts a string to pascal case with the option to remove underscores /// </summary> /// <param name="text">String to convert</param> /// <param name="removeUnderscores">Option to remove underscores</param> /// <returns></returns> public static string ToPascalCase(this string text, bool removeUnderscores, CultureInfo culture) { if (String.IsNullOrEmpty(text)) return text; text = text.Replace("_", " "); string joinString = removeUnderscores ? String.Empty : "_"; string[] words = text.Split(' '); if (words.Length > 1 || words[0].IsUpperCase()) { for (int i = 0; i < words.Length; i++) { if (words[i].Length > 0) { string word = words[i]; string restOfWord = word.Substring(1); if (restOfWord.IsUpperCase()) restOfWord = restOfWord.ToLower(culture); char firstChar = char.ToUpper(word[0], culture); words[i] = String.Concat(firstChar, restOfWord); } } return String.Join(joinString, words); } return String.Concat(words[0].Substring(0, 1).ToUpper(culture), words[0].Substring(1)); } /// <summary> /// Converts a string to camel case /// </summary> /// <param name="lowercaseAndUnderscoredWord">String to convert</param> /// <returns>String</returns> public static string ToCamelCase(this string lowercaseAndUnderscoredWord, CultureInfo culture) { return MakeInitialLowerCase(ToPascalCase(lowercaseAndUnderscoredWord, culture)); } /// <summary> /// Convert the first letter of a string to lower case /// </summary> /// <param name="word">String to convert</param> /// <returns>string</returns> public static string MakeInitialLowerCase(this string word) { return String.Concat(word.Substring(0, 1).ToLower(), word.Substring(1)); } /// <summary> /// Checks to see if a string is all uppper case /// </summary> /// <param name="inputString">String to check</param> /// <returns>bool</returns> public static bool IsUpperCase(this string inputString) { return Regex.IsMatch(inputString, @"^[A-Z]+$"); } /// <summary> /// Add underscores to a pascal-cased string /// </summary> /// <param name="pascalCasedWord">String to convert</param> /// <returns>string</returns> public static string AddUnderscores(this string pascalCasedWord) { return Regex.Replace( Regex.Replace(Regex.Replace(pascalCasedWord, @"([A-Z]+)([A-Z][a-z])", "$1_$2"), @"([a-z\d])([A-Z])", "$1_$2"), @"[-\s]", "_"); } /// <summary> /// Add dashes to a pascal-cased string /// </summary> /// <param name="pascalCasedWord">String to convert</param> /// <returns>string</returns> public static string AddDashes(this string pascalCasedWord) { return Regex.Replace( Regex.Replace( Regex.Replace(pascalCasedWord, @"([A-Z]+)([A-Z][a-z])", "$1-$2"), @"([a-z\d])([A-Z])", "$1-$2"), @"[\s]", "-"); } /// <summary> /// Add an undescore prefix to a pascasl-cased string /// </summary> /// <param name="pascalCasedWord"></param> /// <returns></returns> public static string AddUnderscorePrefix(this string pascalCasedWord) { return string.Format("_{0}", pascalCasedWord); } /// <summary> /// Return possible variants of a name for name matching. /// </summary> /// <param name="name">String to convert</param> /// <param name="culture">The culture to use for conversion</param> /// <returns>IEnumerable<string></returns> public static IEnumerable<string> GetNameVariants(this string name, CultureInfo culture) { if (String.IsNullOrEmpty(name)) yield break; yield return name; // try camel cased name yield return name.ToCamelCase(culture); // try lower cased name yield return name.ToLower(culture); // try name with underscores yield return name.AddUnderscores(); // try name with underscores with lower case yield return name.AddUnderscores().ToLower(culture); // try name with dashes yield return name.AddDashes(); // try name with dashes with lower case yield return name.AddDashes().ToLower(culture); // try name with underscore prefix yield return name.AddUnderscorePrefix(); // try name with underscore prefix, using camel case yield return name.ToCamelCase(culture).AddUnderscorePrefix(); } } /* * 与XML有关的扩展方法 */ public static class XmlExtensions { /// <summary> /// Returns the name of an element with the namespace if specified /// </summary> /// <param name="name">Element name</param> /// <param name="namespace">XML Namespace</param> /// <returns></returns> public static XName AsNamespaced(this string name, string @namespace) { XName xName = name; if (@namespace.HasValue()) xName = XName.Get(name, @namespace); return xName; } } /* * 与日期Datatime有关的扩展方法 */ public static class TimeExtensions { public static DateTime FromNow(this TimeSpan value) { return new DateTime((DateTime.Now + value).Ticks); } public static DateTime FromUnixTime(this long seconds) { var time = new DateTime(1970, 1, 1); time = time.AddSeconds(seconds); return time.ToLocalTime(); } public static long ToUnixTime(this DateTime dateTime) { var timeSpan = (dateTime - new DateTime(1970, 1, 1)); var timestamp = (long) timeSpan.TotalSeconds; return timestamp; } } /* * 与集合Collection有关的扩展方法 */ public internal static class CollectionExtensions { public static IEnumerable<T> AsEnumerable<T>(this T item) { return new[] {item}; } public static IEnumerable<T> And<T>(this T item, T other) { return new[] {item, other}; } public static IEnumerable<T> And<T>(this IEnumerable<T> items, T item) { foreach (var i in items) { yield return i; } yield return item; } public static K TryWithKey<T, K>(this IDictionary<T, K> dictionary, T key) { return dictionary.ContainsKey(key) ? dictionary[key] : default(K); } public static IEnumerable<T> ToEnumerable<T>(this object[] items) where T : class { foreach (var item in items) { var record = item as T; yield return record; } } public static void ForEach<T>(this IEnumerable<T> items, Action<T> action) { foreach (var item in items) { action(item); } } public static void AddRange(this IDictionary<string, string> collection, NameValueCollection range) { foreach (var key in range.AllKeys) { collection.Add(key, range[key]); } } public static string ToQueryString(this NameValueCollection collection) { var sb = new StringBuilder(); if (collection.Count > 0) { sb.Append("?"); } var count = 0; foreach (var key in collection.AllKeys) { sb.AppendFormat("{0}={1}", key, collection[key].UrlEncode()); count++; if (count >= collection.Count) { continue; } sb.Append("&"); } return sb.ToString(); } public static string Concatenate(this WebParameterCollection collection, string separator, string spacer) { var sb = new StringBuilder(); var total = collection.Count; var count = 0; foreach (var item in collection) { sb.Append(item.Name); sb.Append(separator); sb.Append(item.Value); count++; if (count < total) { sb.Append(spacer); } } return sb.ToString(); } } }