常見.NET功能程式碼彙總 (2)
23,獲取和設定分級快取
獲取快取:首先從本地快取獲取,如果沒有,再去讀取分散式快取 寫快取:同時寫本地快取和分散式快取
private static T GetGradeCache<T>(string key) where T:struct { MemoryCacheManager localCache = MemoryCacheManager.Instance; if (!localCache.IsSet(key)) { //本地不存在此快取 T remoteValue = MemCacheManager.Instance.Get<T>(key); if (!ValueType.Equals(remoteValue, default(T))) { //如果遠端有 localCache.Set(key, remoteValue, 1); } else { localCache.SetFromSeconds(key, default(T), 10); } return remoteValue; } T value = localCache.Get<T>(key); return value; } private static void SetGradeCache<T>(string key,T Value,int time) where T : struct { MemoryCacheManager localCache = MemoryCacheManager.Instance; localCache.Remove(key); localCache.Set(key, Value, time); MemCacheManager.Instance.Remove(key); MemCacheManager.Instance.Set(key, Value, time); }
24,求相對目錄的絕對路徑
有時候,我們需要求相對於當前根目錄的相對目錄,比如將日誌檔案儲存在站點目錄之外,我們可以使用 ../logs/ 的方式:
string vfileName = string.Format("../logs/{0}_{1}_{2}.log", logFileName, System.Environment.MachineName, DateTime.Now.ToString("yyyyMMdd")); string rootPath = HttpContext.Current.Server.MapPath("/"); string targetPath = System.IO.Path.Combine(rootPath, vfileName); string fileName = System.IO.Path.GetFullPath(targetPath); string fileDir = System.IO.Path.GetDirectoryName(fileName); if (!System.IO.Directory.Exists(fileDir)) System.IO.Directory.CreateDirectory(fileDir);
這個程式碼會在站點目錄之外的日誌目錄,建立一個 代機器名稱的按照日期區分的日誌檔案。
25,多次嘗試寫日誌檔案方法
日誌檔案可能會併發的寫入,此時可能會提示“檔案被另外一個程序佔用”,因此可以多次嘗試寫入。下面的方法會遞迴的進行檔案寫入嘗試,如果嘗試次數用完才會最終報錯。
/// <summary> /// 儲存日誌檔案 /// </summary> /// <param name="logFileName">不帶副檔名檔名</param> /// <param name="logText">日誌內容</param> /// <param name="tryCount">如果出錯的嘗試次數,建議不大於100,如果是0則不嘗試</param> public static void SaveLog(string logFileName, string logText, int tryCount) { string vfileName = string.Format("..\logs\{0}_{1}_{2}.log", logFileName, System.Environment.MachineName, DateTime.Now.ToString("yyyyMMdd")); string rootPath = System.AppDomain.CurrentDomain.BaseDirectory; string targetPath = System.IO.Path.Combine(rootPath, vfileName); string fileName = System.IO.Path.GetFullPath(targetPath); string fileDir = System.IO.Path.GetDirectoryName(fileName); if (!System.IO.Directory.Exists(fileDir)) System.IO.Directory.CreateDirectory(fileDir); try { System.IO.File.AppendAllText(fileName, logText); tryCount = 0; } catch (Exception ex) { if (tryCount > 0) { System.Threading.Thread.Sleep(1000); logText = logText + "rnSaveLog,try again times =" + tryCount + " ,Error:" + ex.Message; tryCount--; SaveLog(logFileName, logText, tryCount); } else { throw new Exception("Save log file Error,try count more times!"); } } }
26,ASP.NET獲取客戶端的IP地址
string GetRemoteIP()
{
string result = HttpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (null == result || result == String.Empty)
{
result = HttpContext.Request.ServerVariables["REMOTE_ADDR"];
}
if (null == result || result == String.Empty)
{
result = HttpContext.Request.UserHostAddress;
}
return result;
27,ASP.NET MVC 在Action裡面獲取請求的URL
可以分為3種方式, 1)ASP.NET MVC 在控制器的預設Action裡面獲取請求其它Action的路徑 比如在預設的 Index Action裡面獲取路徑,如下:
string sso_url= "http://" + Request.Url.Authority + Request.Url.AbsolutePath + "/SSO?id=" + userid;
2)在其它Action裡面獲取當前控制器的路徑
string ctrName = RouteData.Values["controller"].ToString();
string redirectUrl = "http://" + Request.Url.Authority + "/" + ctrName + "/SSO?id=" + userid;
3)直接獲取當前Action請求的路徑
string url=Request.Url.ToString();
28,ASP.NET MVC Action返回可以在瀏覽器直接檢視的純文字資訊
需要指定Context的contentType 為“text/plain”,程式碼如下:
public ActionResult SendMessage()
{
string txt="你好!";
return Content(text, "text/plain", System.Text.Encoding.UTF8);
}
29,使用Linq2XML讀寫XML
這裡主要使用XDocument,XElement物件來操作XML內容,如下程式碼:
public static class XDocumentExtentsion
{
//生成XML的申明部分
public static string ToStringWithDeclaration(this XDocument doc, SaveOptions options = SaveOptions.DisableFormatting)
{
return doc.Declaration.ToString() + doc.ToString(options);
}
}
public string CreateMsgResult(string loginUserId,string corpid, string msg,string ts)
{
var xDoc = new XDocument(
new XDeclaration("1.0", "UTF-8", null),
new XElement("result",
new XElement("corpid", corpid),
new XElement("userid", loginUserId),
new XElement("ts", ts),
new XElement("sendmsg", msg)
));
return xDoc.ToStringWithDeclaration();
}
public ResponseMessage ParseXMLString(string xml)
{
var xDoc = XDocument.Parse(xml);
if (xDoc == null) return null;
var root = xDoc.Element("result");
if(root==null)
throw new Exception ("not found the 'result' root node,input XMLrn"+xml);
ResponseMessage result =
new ResponseMessage()
{
ErrorCode = root.Element("rescode").Value,
ErrorMessage = root.Element("resmsg").Value,
RedirectUrl = root.Element("redirect_url") == null ? "" : root.Element("redirect_url").Value
};
return result;
}
30,訪問Web內容的自定義程式碼
使用 HttpWebRequest和HttpWebResponse 物件完成Web訪問,如果是.NET 4.5,建議直接使用 HttpClient物件:
/// <summary>
/// 獲取請求結果
/// </summary>
/// <param name="requestUrl">請求地址</param>
/// <param name="timeout">超時時間(秒)</param>
/// <param name="requestXML">請求xml內容</param>
/// <param name="isPost">是否post提交</param>
/// <param name="encoding">編碼格式 例如:utf-8</param>
/// <param name="errorMsg">丟擲的錯誤資訊</param>
/// <returns>返回請求結果</returns>
public static string HttpWebRequest(string requestUrl, int timeout, string requestXML, bool isPost, string encoding, out string errorMsg, string contentType = "application/x-www-form-urlencoded")
{
errorMsg = string.Empty;
string result = string.Empty;
try
{
byte[] bytes = System.Text.Encoding.GetEncoding(encoding).GetBytes(requestXML);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
request.Referer = requestUrl;
request.Method = isPost ? "POST" : "GET";
request.Timeout = timeout * 1000;
if (isPost)
{
request.ContentType = contentType;// "application/x-www-form-urlencoded";
request.ContentLength = bytes.Length;
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
}
}
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
if (responseStream != null)
{
StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.GetEncoding(encoding));
result = reader.ReadToEnd();
reader.Close();
responseStream.Close();
request.Abort();
response.Close();
return result.Trim();
}
}
catch (Exception ex)
{
errorMsg =string.Format("Error Message:{0},Request Url:{1},StackTrace:{2}", ex.Message ,requestUrl , ex.StackTrace);
}
return result;
}
31,自定義瀏覽器協議(偽協議),實現web程式呼叫本地程式
(轉自 http://blog.sina.com.cn/s/blog_4a77f0630100hav3.html) 最近專案遇到這麼個問題。客戶要求用web頁面,點選一個連結,呼叫本地的一個程式。
參考了一下qq的方式。 tencent://Message/?Uin=000000&websiteName=qzone.qq.com&Menu=yes
在登錄檔裡面新增下面,就能實現,詳細內容見原文
32,執行緒安全的向集合新增元素
有時候,向一個List物件呼叫Add 方法,會出現“索引超出了陣列界限”這樣的問題,此時可以考慮使用執行緒安全的集合,但對於業務上設定了集合的最大值的情況下,用執行緒安全集合就有點重了,效率不高,此時可以通過 Interlocked.CompareExchange 來實現,具體程式碼如下:
private int length=0;
private int maxLength=50;
private int[] Arr=new int[maxLength];
//使用迴圈陣列,安全的新增元素
void Add(int value){
int p= Interlocked.CompareExchange(ref length,0,maxLength);
if(p==length)
{
//說明length變數並且沒有達到最大值,並安全的返回length當時的值
Arr[p]=value;
}
else
{
//陣列元素已經達到上限,需要觸發另外的操作,比如將陣列全部輸出
// To Do
//之後,再將當前位置的元素寫入
//此時,length可能是0,也可能是其它值
Arr[length]=value;
}
Interlocked.Increment(ref length);
}
33,WPF繫結非同步更新的資料集合
最近做一個WPF專案,後端API推送過來的資料要更新WPF介面的資料,發現有些資料沒有跟後端資料狀態一致。通常情況下,WPF繫結的Model資料集合都是繼承於ObservableCollection 的,但是在當前情況下會有問題,這是可以封裝一個非同步的資料集合:
public class AsyncObservableCollection<T> : ObservableCollection<T>
{
//獲取當前執行緒的SynchronizationContext物件
private SynchronizationContext _synchronizationContext = SynchronizationContext.Current;
public AsyncObservableCollection() { }
public AsyncObservableCollection(IEnumerable<T> list) : base(list) { }
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
//如果操作發生在同一個執行緒中,不需要進行跨執行緒執行
RaiseCollectionChanged(e);
}
else
{
//如果不是發生在同一個執行緒中
//準確說來,這裡是在一個非UI執行緒中,需要進行UI的更新所進行的操作
_synchronizationContext.Post(RaiseCollectionChanged, e);
}
}
private void RaiseCollectionChanged(object param)
{
// 執行
base.OnCollectionChanged((NotifyCollectionChangedEventArgs)param);
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (SynchronizationContext.Current == _synchronizationContext)
{
// Execute the PropertyChanged event on the current thread
RaisePropertyChanged(e);
}
else
{
// Post the PropertyChanged event on the creator thread
_synchronizationContext.Post(RaisePropertyChanged, e);
}
}
private void RaisePropertyChanged(object param)
{
// We are in the creator thread, call the base implementation directly
base.OnPropertyChanged((PropertyChangedEventArgs)param);
}
}
更多資訊,請參考: