AutoFac

来源:https://www.cnblogs.com/SmileIven/archive/2018/08/24/9530967.html
-Advertisement-
Play Games

using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace FB.CMS.MvcSite.App_Start { using Autofac; using Autofac... ...


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
 
namespace FB.CMS.MvcSite.App_Start
{
    using Autofac;
    using Autofac.Integration.Mvc;
    using System.Reflection;
    using System.Web.Mvc;
 
    /// <summary>
    /// 這個類是我自己定義的一個類,主要用初始化AutoFac容器的相關數據
    /// </summary>
    public class AutoFacConfig
    {
 
 
        public static void Register()
        {
            //初始化AutoFac的相關功能
            /*
             1.0 告訴AutoFac初始化數據倉儲層FB.CMS.Repository.dll中所有類的對象實例。這些對象實例以其介面的形式保存在AutoFac容器中
             2.0 告訴AutoFac初始化業務邏輯層FB.CMS.Services.dll中所有類的對象實例。這些對象實例以其介面的形式保存在AutoFac容器中
             3.0 將MVC預設的控制器工廠替換成AutoFac的工廠
             */
 
            //第一步: 構造一個AutoFac的builder容器
            ContainerBuilder builder = new Autofac.ContainerBuilder();
 
            //第二步:告訴AutoFac控制器工廠,控制器類的創建去哪些程式集中查找(預設控制器工廠是去掃描bin目錄下的所有程式集)
            //2.1 從當前運行的bin目錄下載入FB.CMS.MvcSite.dll程式集
            Assembly controllerAss = Assembly.Load("FB.CMS.MvcSite");
 
            //2.2 告訴AutoFac控制器工廠,控制器的創建從controllerAss中查找(註意:RegisterControllers()方法是一個可變參數,如果你的控制器類的創建需要去多個程式集中查找的話,
        那麼我們就再用Assembly controllerBss=Assembly.Load("需要的程式集名")載入需要的程式集,然後與controllerAss組成數組,然後將這個數組傳遞到RegisterControllers()方法中)
builder.RegisterControllers(controllerAss); //第三步:告訴AutoFac容器,創建項目中的指定類的對象實例,以介面的形式存儲(其實就是創建數據倉儲層與業務邏輯層這兩個程式集中所有類的對象實例,然後以其介面的形式保存到AutoFac容器記憶體中,
        當然如果有需要也可以創建其他程式集的所有類的對象實例,這個只需要我們指定就可以了)
//3.1 載入數據倉儲層FB.CMS.Repository這個程式集。 Assembly repositoryAss = Assembly.Load("FB.CMS.Repository"); //3.2 反射掃描這個FB.CMS.Repository.dll程式集中所有的類,得到這個程式集中所有類的集合。 Type[] rtypes = repositoryAss.GetTypes(); //3.3 告訴AutoFac容器,創建rtypes這個集合中所有類的對象實例 builder.RegisterTypes(rtypes) .AsImplementedInterfaces(); //指明創建的rtypes這個集合中所有類的對象實例,以其介面的形式保存 //3.4 載入業務邏輯層FB.CMS.Services這個程式集。 Assembly servicesAss = Assembly.Load("FB.CMS.Services"); //3.5 反射掃描這個FB.CMS.Services.dll程式集中所有的類,得到這個程式集中所有類的集合。 Type[] stypes = servicesAss.GetTypes(); //3.6 告訴AutoFac容器,創建stypes這個集合中所有類的對象實例 builder.RegisterTypes(stypes) .AsImplementedInterfaces(); //指明創建的stypes這個集合中所有類的對象實例,以其介面的形式保存 //第四步:創建一個真正的AutoFac的工作容器 var container = builder.Build(); //我們已經創建了指定程式集的所有類的對象實例,並以其介面的形式保存在AutoFac容器記憶體中了。那麼我們怎麼去拿它呢? //從AutoFac容器內部根據指定的介面獲取其實現類的對象實例 //假設我要拿到IsysFunctionServices這個介面的實現類的對象實例,怎麼拿呢? //var obj = container.Resolve<IsysFunctionServices>(); //只有有特殊需求的時候可以通過這樣的形式來拿。一般情況下沒有必要這樣來拿,因為AutoFac會自動工作
        (即:會自動去類的帶參數的構造函數中找與容器中key一致的參數類型,並將對象註入到類中,其實就是將對象賦值給構造函數的參數)
//第五步:將當前容器中的控制器工廠替換掉MVC預設的控制器工廠。(即:不要MVC預設的控制器工廠了,用AutoFac容器中的控制器工廠替代)此處使用的是將AutoFac工作容器交給MVC底層 (需要using System.Web.Mvc;) DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); //我們知道控制器的創建是調用MVC預設的控制器工廠,預設的控制器工廠是調用控制器類的無參構造函數 //可是我們如果要使用AutoFac自動工廠,將對象通過構造函數註入類中,那麼這個構造函數就需要帶參數 //如果我們將控制器的無參構造函數刪除,保留帶參數的構造函數,MVC預設的控制器工廠來創建控制的時候 //就會去調用無參的構造函數,可是這時候發現沒有無參的構造函數於是就報“沒有為該對象定義無參數的構造函數”錯誤 //既然報錯,那我們如果保留無參的構造函數,同時在聲明一個帶參數的構造函數是否可行呢? //答案;行是行,但是創建控制器的時候,MVC預設的控制器工廠調用的是無參構造函數,它並不會去調用有參的構造函數 //這時候,我們就只能將AutoFac它的控制器工廠替換調用MVC預設的控制器工廠(控制器由AutoFac的控制器工廠來創建) //而AutoFac控制器工廠在創建控制的時候只會掃描帶參數的構造函數,並將對象註入到帶參數的構造函數中 //AutofacDependencyResolver這個控制器工廠是繼承了 IDependencyResolver介面的,而IDependencyResolver介面是MVC的東西 //MVC預設的控制器工廠名字叫:DefaultControllerFactory //具體參考:http://www.cnblogs.com/artech/archive/2012/04/01/controller-activation-032.html } } }
using FB.CMS.MvcSite.App_Start;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
 
namespace FB.CMS.MvcSite
{
    // 註意: 有關啟用 IIS6 或 IIS7 經典模式的說明,
    // 請訪問 http://go.microsoft.com/?LinkId=9394801
 
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            
            AreaRegistration.RegisterAllAreas();
 
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
 
            //第一: 在網站一啟動的時候就初始化AutoFac的相關功能
            /*
             1.0 告訴AutoFac初始化數據倉儲層FB.CMS.Repository.dll中所有類的對象實例。這些對象實例以其介面的形式保存在AutoFac容器中
             2.0 告訴AutoFac初始化業務邏輯層FB.CMS.Services.dll中所有類的對象實例。這些對象實例以其介面的形式保存在AutoFac容器中
             3.0 將MVC預設的控制器工廠替換成AutoFac的工廠
             */
 
            //具體做法就是我們去App_Start文件夾下創建一個AutoFacConfig類,具體實現什麼功能去這個類中實現。然後再這裡調用下這個類
            AutoFacConfig.Register();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace FB.CMS.MvcSite.Controllers
{
    using FB.CMS.IServices;
    public class HomeController : Controller
    {
        IsysFunctionServices dal;
        public HomeController(IsysFunctionServices dal) //依賴構造函數進行對象註入
        {
            this.dal = dal; //在構造函數中初始化HomeController控制器類的dal屬性 (這個dal屬性的類型是IsysFunctionServices)
        }
 
        public ActionResult Index()
        {
            var a = dal.QueryWhere(r => r.fID > 20).ToList(); //查詢
            return View();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace FB.CMS.Repository
{
    using FB.CMS.IRepository;
    using System.Data.Entity;
    using System.Data.Entity.Infrastructure;
    using System.Linq.Expressions;
    using System.Runtime.Remoting.Messaging;
    using System.Threading;
    public class BaseDal<TEntity> : IBaseDal<TEntity> where TEntity : class
    {
        //BaseDbContext db = new BaseDbContext();
 
        //對創建上下文容器類對象進行優化(原理:一個線程下我們只創建一個上下文容器類對象,然後保存到線程緩存當中去,當同一個線程過來的時候,就從線程緩存當中取上下文容器類對象)
        public BaseDbContext db
        {
            get
            {
                //獲取BaseDbContext的完全限定名,其實這個名字沒什麼特別的意義,僅僅是一個名字而已,也可以取別的名字的
                string threadName = typeof(BaseDbContext).FullName;
                //獲取key為threadName的這個線程緩存(CallContext就是線程緩存容器類)
                object dbObj = CallContext.GetData(threadName);
                //如果key為threadName的線程緩存不存在
                if (dbObj == null)
                {
                    //創建BaseDbContext類的對象實例
                    dbObj = new BaseDbContext();
                    //將這個BaseDbContext類的對象實例保存到線程緩存當中(以鍵值對的形式進行保存的,我這就將key設為當前線程的完全限定名了)
                    CallContext.SetData(threadName, dbObj);
                    return dbObj as BaseDbContext;
                }
                return dbObj as BaseDbContext;
            }
 
        }
        DbSet<TEntity> _dbset;
        public BaseDal()
        {
            this._dbset = db.Set<TEntity>(); //初始化
        }
 
        #region 增加
        public void AddEnity(TEntity model)
        {
            if (model == null)
            {
                throw new Exception("moddel不能為null");
            }
            this._dbset.Add(model);
 
 
        }
 
        #endregion
 
        #region 物理刪除
        /// <summary>
        /// 刪除
        /// </summary>
        /// <param name="model">實體類</param>
        /// <param name="isaddedContext">是否物理刪除</param>
        public void DeleteEntity(TEntity model, bool isaddedContext)
        {
            if (model == null)
            {
                throw new Exception("DeleteEntity方法中的model不能為null");
            }
            //如果僅僅是邏輯刪除的話,那我們只要調用編輯方法將標識為邏輯刪除的那個欄位修改為true就可以了。
            if (isaddedContext == true)
            {
                this._dbset.Attach(model);
 
            }
            this._dbset.Remove(model);
        }
 
        #endregion
 
        #region 查尋
        /// <summary>
        /// 普通帶條件查詢
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public IQueryable<TEntity> QueryWhere(Expression<Func<TEntity, bool>> where)
        {
            return this._dbset.Where(where);
        }
 
        /// <summary>
        /// 連表查詢
        /// </summary>
        /// <param name="where">連表查詢的條件篩選查詢</param>
        /// <param name="tablesName">要做連表查詢的所有表名集合</param>
        /// <returns></returns>
        public IQueryable<TEntity> QueryJoin(Expression<Func<TEntity, bool>> where, string[] tablesName)
        {
            if (tablesName == null || tablesName.Any() == false)
            {
                throw new Exception("連表查詢最少也要一個表,所有QueryJoin方法中tablesName中最少也需要有一個表名");
            }
 
            DbQuery<TEntity> query = this._dbset;
            foreach (string tableName in tablesName)
            {
                //不斷的連表,直到把tablesName里的所有表都連完
                query = query.Include(tableName);
            }
            return query.Where(where); //然後對連表進行條件篩選查詢
        }
 
        /// <summary>
        /// 帶條件的分頁查詢
        /// </summary>
        /// <typeparam name="TKey">按哪個欄位進行排序</typeparam>
        /// <param name="pageindex">當前頁</param>
        /// <param name="pagesize">頁大小</param>
        /// <param name="rowCount">數據總條數</param>
        /// <param name="order">排序</param>
        /// <param name="where">篩選條件</param>
        /// <returns></returns>
        public IQueryable<TEntity> QueryByPage<TKey>(int pageindex, int pagesize, out int rowCount, Expression<Func<TEntity, TKey>> order, Expression<Func<TEntity, bool>> where)
        {
            //獲取總條數
            rowCount = this._dbset.Count(where);
 
            //建議將這個Where條件語句放在前面,如果你放到後面,分頁的時候可能存在問題。
            return this._dbset.Where(where).OrderByDescending(order).Skip((pageindex - 1) * pagesize).Take(pagesize);
 
        }
 
        /// <summary>
        /// 調用存儲過程或執行SQL語句(但是我們不推薦執行sql語句)
        /// </summary>
        /// <typeparam name="TElement">
        /// 因為存儲過程返回的數據不一定就是TEntity這個實體,因為存儲過返回的結果集有可能是自己拼接出來的,所以這個方法的返回結果
        /// 為Lsit<TEntity>就不合適了。 這個 TElement是在調用的存儲過程的時候傳入的一個實體,此實體必須和調用的存儲過程的返回結集
        /// 中的欄位名稱保存一致(你這個存儲過程返回有多個欄位,那麼你這個實體中就應該有多少個屬性)
        /// </typeparam>
        /// <param name="sql">
        /// 假設我創建了這麼一個存儲過程:
        /// create proc proc_T_UserInfo_Paging2(@pageSize int,@currentPage int,@CountData  )  
        /// 那現在我們調用這個存儲過程,那麼這個SQL語句的寫法就是:
        /// proc_T_UserInfo_Paging2 @pageSize int,@currentPage int,@CountData       /// 
        /// </param>
        /// <param name="prms">參數化查詢的參數數組</param>
        /// <returns></returns>
        public List<TElement> RunProc<TElement>(string sql, params object[] prms)
        {
            return db.Database.SqlQuery<TElement>(sql, prms).ToList();
        }
        #endregion
 
        #region 編輯
        /// <summary>
        /// 編輯
        /// </summary>
        /// <param name="model">實體</param>
        /// <param name="propertyNames">要編輯的的所有屬性名稱序列</param>
        public void EditEntity(TEntity model, string[] propertyNames)
        {
            if (model == null)
            {
                throw new Exception("EditEntity方法中的參數model不能為null");
            }
            if (propertyNames.Any() == false || propertyNames == null)
            {
                throw new Exception("EditEntity方法中的參數propertyNames最少需要一個屬性");
            }
            System.Data.Entity.Infrastructure.DbEntityEntry entry = db.Entry(model);
            entry.State = System.Data.EntityState.Unchanged;
            foreach (string item in propertyNames)
            {
                entry.Property(item).IsModified = true;
            }
            db.Configuration.ValidateOnSaveEnabled = false;
        }
 
        #endregion
 
        #region 統一保存
        public int SaveChanges()
        {
            return db.SaveChanges();
        }
        #endregion
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace FB.CMS.Site.Controllers
{
    using FB.CMS.IRepository;
    
    public class HomeController : Controller
    {
        IsysFunctionRepository fundal;
        IsysKeyValueRepository kvdal;
 
        //我們在通過AutoFac將IsysFunctionRepository和IsysKeyValueRepository的兩個實現類的對象實例註入到當前構造函數中
        //那麼在註入IsysFunctionRepository這實現類的對象的時候就會執行到sysFunctionRepository類,而這個sysFunctionRepository類
        //又是繼承了BaseDal類,然後就會去執行BaseDal類的構造函數,而在BaseDal這個類的構造函數中我們執行了
        //this._dbset = db.Set<TEntity>()這段代碼,這段代碼中使用了db這個上下文容器類對象。既然使用了這個對象,所以就會首先初始化這個對象
        //按照平常的寫法,一般都是直接new一個上下文容器對象,即:BaseDbContext db = new BaseDbContext();
        //然後當我們再對構造函數的參數IsysKeyValueRepository kvdal進行對象註入的時候,同樣的原理又會執行一次
        //BaseDbContext db = new BaseDbContext();即又創建了一個上下文容器類對象。所以說當我們通過構造函數一次性註入多個對象的時候
        //會創建多個上下文容器類對象。所以這樣的做法是非常不好的。因為我們如果在同一個線程裡面用兩個上下文容器類對象分別去對數據增刪改
        //的後,【最後統一執行db.SaveChanges()】;這時候會發現只有後面的那個上下文容器類對象對數據的增刪改操作成功,而前面的那個上下文容器類對象對數據的增刪
        public HomeController(IsysFunctionRepository fundal, IsysKeyValueRepository kvdal)
        {
            this.fundal = fundal;
            this.kvdal = kvdal;
        }
        
        public ActionResult Index()
        {
            //var model = fundal.QueryWhere(r => r.fID == 20).FirstOrDefault();
            //model.fName = "預設888";
            //fundal.SaveChanges(); //執行保存修改其實就已經操作一次資料庫了
 
            //var model2 = kvdal.QueryWhere(r => r.KID == 3).FirstOrDefault();
            //model2.KName = "公司88"; 
 
            //fundal.SaveChanges(); //這裡又執行一次保存修改操作,又執行了一個資料庫,
 
 
            //那我們就希望在同一個控制器中(同一個控制中意味著在同一個線程當中)不管操作多少個上下文容器類對象對數據的操作
            //我們只希望最後只執行已給SaveChanges(),這樣就能保障最少次的對資料庫的操作。從而提高性能
            //那我們怎麼做呢?其實很簡單,當我們執行構造函數對多個對象進行註入的時候,我們保證只有一個上下文容器類對象實例
            //當我們在Home控制器中通過構造函數註入兩個對象,那麼這個Home控制器會有一個線程進行管理,那麼當這個線程過來的時候
            //我們就創建先去一個線程緩存中去獲取一下這個線程名對應的緩存,如果緩存不存在,那麼我們就創建一個上下文容器類對象實例
            //並將這個對象實例存儲到線程緩存當中,然後返回這個上下文容器類對象。如果緩存存在,那麼就直接獲取這個緩存進行返回
            //這樣就保證了同一線程下,只有個上下文容器類實例對象,這樣我們就可以用任何上下文容器類對象對數據的增刪改後,最後只
            //需要用任何一個上下文容器類對象執行一次SaveChanges()就可以了
 
            var model = fundal.QueryWhere(r => r.fID == 20).FirstOrDefault();
            model.fName = "預設888";
            //fundal.SaveChanges(); //執行保存修改其實就已經操作一次資料庫了
 
            var model2 = kvdal.QueryWhere(r => r.KID == 3).FirstOrDefault();
            model2.KName = "公司88";
 
            fundal.SaveChanges(); //通過對BaseDal中對創建上下文容器類的優化後,我們看到在同一個線程中 兩個上下文容器類對象(通過優化後其實這個兩個上下文容器類對象其實是同一個上下文容器類對象)
                  同時對數據進行改的操作,最後只執行了一個fundal.SaveChanges(); 方法,就將數據成功保存了。這樣就達到了最少操作資料庫。性能提升了
return View(model); } } }
   
public ActionResult Index()
{
    ContainerBuilder builder = new ContainerBuilder();
    builder.RegisterType<UserInfoSevices>(); //想拿到UserInfoSevices類的實例
    builder.RegisterType<UserInfoRepository>().As<IUserInfoRepository>(); //與之關聯的UserInfoRepository類也需要拿到,並轉化成介面的形式保存
    var aa = builder.Build().Resolve<UserInfoSevices>().QueryModel(r => r.Age > 0); //在這裡使用
 
    return View();
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 01.1 Windows環境下JDK安裝與環境變數配置詳細的圖文教程 本節內容:JDK安裝與環境變數配置 以下是詳細步驟 一、準備工具: 1.JDK JDK 可以到官網下載 "http://www.oracle.com/technetwork/java/javase/downloads/jdk8 d ...
  • 前言 眾所周知,Java中有多種針對文件的操作類,以面向位元組流和字元流可分為兩大類,這裡以寫入為例: 面向位元組流的:FileOutputStream 和 BufferedOutputStream 面向字元流的:FileWriter 和 BufferedWriter 近年來發展出New I/O ,也叫 ...
  • 今日內容介紹 1、Java開發環境搭建 2、HelloWorld案例 3、註釋、關鍵字、標識符 4、數據(數據類型、常量) ...
  • ASP.NET Core MVC中的Filter作用是在請求處理管道的某些階段之前或之後可以運行特定的代碼。 Filter特性在之前的ASP.NET MVC中已經出現,但過去只有Authorization,Exception,Action,Result四種類型,現在又增加了一種Resource類型。 ...
  • *必須要有無線網卡才能設置WIFI首先打開電腦,選中“電腦”或者“我的電腦”,右擊進入“管理”選項“。打開“電腦管理”視窗之後,在左欄菜單選項中找到“服務和應用程式”下的“服務”選項,如圖點擊進入“服務”列表。然後在服務列表最下方找到“WLAN AutoConfig”服務和“WWAN AutoC ...
  • win10在設置顏色里有個從“背景圖片中選取一種主題顏色”的選項,還有在很多內容展示軟體中都使用了這樣的功能。 現在我們需要在 nuget 引用 win2d.uwp 和 Toolkit.uwp 兩個庫。 首先將一個圖片流轉換成 win2d 的 CanvasBitmap 對象,然後通過 CanvasB ...
  • 對窗體加越界限制後,滑鼠拖動窗體越界時,窗體不能動,滑鼠位置可動,但窗體不再越界時,滑鼠位置還能回到滑鼠按下時相對窗體的坐標:1、首先創建一個窗體Form1,然後在窗體上拖一個button1按鈕(主要通過這個按鈕來拖動窗體)2、然後對按鈕添加滑鼠按下事件、滑鼠移動事件和滑鼠抬起事件,事件裡面是對窗體 ...
  • 1.先在VS 的擴展更新中搜索此插件【2015 installer Projects】,點擊下載,安裝需要關閉VS 2.安裝完畢之後新建項目 3.選擇“application folder”項,然後在右邊的空白區域右擊,選擇Add,如下圖 4.選擇需要打包發佈的exe文件 這裡會自動帶出相關聯的dl ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...