• 常见.NET功能代码汇总 (2)


    常见.NET功能代码汇总

    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 + "
    SaveLog,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 XML
    "+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);
        }
    }

    更多信息,请参考:

    WPF多线程UI更新——两种方法

    绑定到异步的ObservableCollection

  • 相关阅读:
    JS设计模式的坑
    nth-child()和nth-of-type()的区别,以及如何在nth中添加变量和表达式
    for循环中,使用闭包和不使用闭包的区别以及原因
    JS闭包的基础知识,闭包的本质,闭包的作用,闭包的间谍属性和闭包的遗憾
    前端和后端数据交互的基本知识和常见方式
    dedecms手机PC同步更新插件的bug修复和前后端调试的经验
    065 女神颜值打分系统
    029 令牌桶算法限流
    04-01 集成学习基础
    028 【博弈论】关于三姬分金(五海盗分赃)的博弈论问题分析
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/5641176.html
Copyright © 2020-2023  润新知