webapi中如何使用依賴注入

來源:互聯網
上載者:User
本篇將要和大家分享的是webapi中如何使用依賴注入,依賴注入這個東西在介面中常用,實際工作中也用的比較頻繁,因此這裡分享兩種在api中依賴注入的方式Ninject和Unity。下面跟著小編一起來看下吧

本篇將要和大家分享的是webapi中如何使用依賴注入,依賴注入這個東西在介面中常用,實際工作中也用的比較頻繁,因此這裡分享兩種在api中依賴注入的方式Ninject和Unity;由於快過年這段時間打算瞭解下vue.js,所以後面對webapi的分享文章可能會慢點更新,希望支援的朋友們多多諒解,畢竟只有不斷充電學習,才能更好的適應it行業吧;本章內容希望大家喜歡,也希望各位多多掃碼支援和推薦謝謝:

» Task並行任務抓取部落格園首頁資訊

» IOC架構Ninject的使用

» IOC架構Unity的使用

下面一步一個腳印的來分享:

» Task並行任務抓取部落格園首頁資訊

首先,咋們需要建立一個部落格資訊實體類 MoBlog ,實體類代碼如下:

public class MoBlog {  public MoBlog() { }  /// <summary>  /// 作者暱稱  /// </summary>  public string NickName { get; set; }  /// <summary>  /// 標題  /// </summary>  public string Title { get; set; }  /// <summary>  ///該篇文字地址  /// </summary>  public string Url { get; set; }  /// <summary>  /// 描述  /// </summary>  public string Des { get; set; }  /// <summary>  /// 頭像圖片地址  /// </summary>  public string HeadUrl { get; set; }  /// <summary>  /// 部落格地址  /// </summary>  public string BlogUrl { get; set; }  /// <summary>  /// 點贊次數  /// </summary>  public int ZanNum { get; set; }  /// <summary>  /// 閱讀次數  /// </summary>  public int ReadNum { get; set; }  /// <summary>  /// 評論次數  /// </summary>  public int CommiteNum { get; set; }  /// <summary>  /// 建立時間  /// </summary>  public DateTime CreateTime { get; set; } }

然後,需要建立一個介面 IBlogsReposity ,並且定義一個如下代碼的方法:

public interface IBlogsReposity {  /// <summary>  /// 擷取部落格資訊  /// </summary>  /// <param name="nTask"></param>  /// <returns></returns>  Task<IEnumerable<MoBlog>> GetBlogs(int nTask); }

注意這裡定義的傳回型別是Task<T>,主要作用是async非同步返回部落格資訊,並且方便使用並行方式抓取不同頁數的資料,因此這裡傳遞了一個int類型的參數nTask(表示任務數量);好了咋們來一起看下具體實現介面的 BoKeYuan 類裡面的代碼:

public class BoKeYuan : IBlogsReposity {  public async Task<IEnumerable<MoBlog>> GetBlogs(int nTask)  {   var blogs = new List<MoBlog>();   try   {    //開啟nTask個任務,讀取前nTask頁資訊    Task<IEnumerable<MoBlog>>[] tasks = new Task<IEnumerable<MoBlog>>[nTask];    for (int i = 1; i <= tasks.Length; i++)    {     tasks[i - 1] = await Task.Factory.StartNew<Task<IEnumerable<MoBlog>>>((page) =>      {       return GetBlogsByPage(Convert.ToInt32(page));      }, i);    }    //30s等待    Task.WaitAll(tasks, TimeSpan.FromSeconds(30));    foreach (var item in tasks.Where(b => b.IsCompleted))    {     blogs.AddRange(item.Result);    }   }   catch (Exception ex)   {   }   return blogs.OrderByDescending(b => b.CreateTime);  }  /// <summary>  ///   /// </summary>  /// <param name="nPage">頁數</param>  /// <returns></returns>  async Task<IEnumerable<MoBlog>> GetBlogsByPage(int nPage)  {   var blogs = new List<MoBlog>();   try   {    var strBlogs = string.Empty;    using (HttpClient client = new HttpClient())    {     strBlogs = await client.GetStringAsync("http://www.cnblogs.com/sitehome/p/" + nPage);    }    if (string.IsNullOrWhiteSpace(strBlogs)) { return blogs; }    var matches = Regex.Matches(strBlogs, "diggnum\"[^>]+>(?<hzan>\\d+)[^:]+(?<burl>http[^\"]+)[^>]+>(?<title>[^<]+)<\\/a>[^=]+=[^=]+=\"(?<hurl>http://(\\w|\\.|\\/)+)[^>]+>[^\\/]+\\/\\/(?<hphoto>[^\"]+)[^<]+<\\/a>(?<bdes>[^<]+)[^\"]+[^=]+=[^>]+>(?<hname>[^<]+)[^2]+(?<bcreatetime>[^<]+)[^\\(]+\\((?<bcomment>\\d+)[^\\(]+\\((?<bread>\\d+)");    if (matches.Count <= 0) { return blogs; }    foreach (Match item in matches)    {     blogs.Add(new MoBlog     {      Title = item.Groups["title"].Value.Trim(),      NickName = item.Groups["hname"].Value.Trim(),      Des = item.Groups["bdes"].Value.Trim(),      ZanNum = Convert.ToInt32(item.Groups["hzan"].Value.Trim()),      ReadNum = Convert.ToInt32(item.Groups["bread"].Value.Trim()),      CommiteNum = Convert.ToInt32(item.Groups["bcomment"].Value.Trim()),      CreateTime = Convert.ToDateTime(item.Groups["bcreatetime"].Value.Trim()),      HeadUrl = "http://" + item.Groups["hphoto"].Value.Trim(),      BlogUrl = item.Groups["hurl"].Value.Trim(),      Url = item.Groups["burl"].Value.Trim(),     });    }   }   catch (Exception ex)   {   }   return blogs;  } }

程式碼分析:

1. Task<IEnumerable<MoBlog>>[] tasks = new Task<IEnumerable<MoBlog>>[nTask]作為並行任務的容器;

2. Task.Factory.StartNew建立對應的任務

3. Task.WaitAll(tasks, TimeSpan.FromSeconds(30));等待容器裡面任務完成30秒後逾時

4. 最後通過把item.Result任務結果添加到集合中,返回我們需要的資料

這裡解析部落格內容資訊用的Regex,這種方式在抓取一定內容上很方便;群裡面有些朋友對正則有點反感,剛接觸的時候覺得挺不好寫的,所以一般都採用更複雜或者其他的解析方式來擷取想要的內容,這裡提出來主要是和這些朋友分享下正則擷取資料是多麼方便,很有必要學習下並且掌握常規的用法,這也是一種苦盡甘來的體驗吧哈哈;

好了咋們建立一個webapi項目取名為 Stage.Api ,使用她自動產生的 ValuesController 檔案裡面的Get方法介面來調用咋們上面實現的部落格抓取方法,代碼如下:

// GET api/values  public async Task<IEnumerable<MoBlog>> Get(int task = 6)  {   task = task <= 0 ? 6 : task;   task = task > 50 ? 50 : task;   IBlogsReposity _reposity = new BoKeYuan();   return await _reposity.GetBlogs(task);  }

這裡使用 IBlogsReposity _reposity = new BoKeYuan(); 來建立和調用具體的實作類別,這裡貼出一個線上抓取部落格首頁資訊的地址(不要告訴dudu):http://www.php.cn/:1001/api/values?task=6;咋們來想象一下,如果這個Get方法中還需要調用其他實現了介面 IBlogsReposity 的部落格抓取類,那咋們又需要手動new一次來建立對應的對象;倘若除了在 ValuesController.cs 檔案中調用了部落格資料抓取,其他檔案還需要這抓取資料的業務,那麼又會不停的new,可能有朋友就會說那弄一個原廠模式怎麼樣,不錯這是可行的一種方式,不過這裡還有其他方法能處理這種問題,比如:ioc依賴注入;因此就有了下面的分享內容。

» IOC架構Ninject的使用

首先,我們要使用ninject需要使用nuget下載安裝包,這裡要注意的是Ninject版本比較多,需要選擇合適自己webapi的版本,我這裡選擇的是:

看起來很老了哈哈,不過咋們能用就行,安裝起來可能需要點時間,畢竟比較大麼也有可能是網路的問題吧;安裝完後咋們建立一個自訂類 NinjectResolverScope 並實現介面 IDependencyScope , IDependencyScope 對應的類庫是 System.Web.Http.dll (註:由於webapi2項目自動產生時候可能勾選了mvc,mvc架構裡面也包含了一個IDependencyScope,所以大家需要注意區分下),好了咋們來直接看下 NinjectResolverScope 實現代碼:

/// <summary> /// 解析 /// </summary> public class NinjectResolverScope : IDependencyScope {  private IResolutionRoot root;  public NinjectResolverScope() { }  public NinjectResolverScope(IResolutionRoot root)  {   this.root = root;  }  public object GetService(Type serviceType)  {   try   {    return root.TryGet(serviceType);   }   catch (Exception ex)   {    return null;   }  }  public IEnumerable<object> GetServices(Type serviceType)  {   try   {    return this.root.GetAll(serviceType);   }   catch (Exception ex)   {    return new List<object>();   }  }  public void Dispose()  {   var disposable = this.root as IDisposable;   if (disposable != null)    disposable.Dispose();   this.root = null;  } }

這裡要注意的是GetService和GetServices方法必須使用 try...catch() 包住,經過多方調試和測試,這裡面會執行除手動bind綁定外的依賴,還會執行幾個其他非手動綁定的執行個體對象,這裡使用try避免拋異常影響到程式(其實咋們可以在這裡用代碼過濾掉非手動綁定的幾個執行個體);這裡也簡單說下這個 NinjectResolverScope 中方法執行的先後順序:GetService=》GetServices=》Dispose,GetService主要用來擷取依賴注入對象的執行個體;好了到這裡咋們還需要一個自訂容器類 NinjectResolverContainer ,該類繼承自上面的 NinjectResolverScope 和實現 IDependencyResolver 介面(其實細心的朋友能發現這個 IDependencyResolver 同樣也繼承了 IDependencyScope ),具體代碼如下:

public class NinjectResolverContainer : NinjectResolverScope, IDependencyResolver {  private IKernel kernel;  public static NinjectResolverContainer Current  {   get   {    var container = new NinjectResolverContainer();    //初始化    container.Initing();    //綁定    container.Binding();    return container;   }  }  /// <summary>  /// 初始化kernel  /// </summary>  void Initing()  {   kernel = new StandardKernel();  }  /// <summary>  /// 綁定  /// </summary>  void Binding()  {   kernel.Bind<IBlogsReposity>().To<BoKeYuan>();  }  /// <summary>  /// 開始執行  /// </summary>  /// <returns></returns>  public IDependencyScope BeginScope()  {   return new NinjectResolverScope(this.kernel.BeginBlock());  } }

這裡能夠看到 IKernel kernel = new StandardKernel(); 這代碼,她們引用都來源於我們安裝的Ninject包,通過調用初始化Initing()後,我們需要在Binding()方法中手動綁定我們對應需要依賴注入的執行個體,Ninject綁定方式有很多種這裡我用的格式是: kernel.Bind<介面>().To<實作類別>(); 如此簡單就實現了依賴注入,每次我們需要添加不同的依賴項的時候只需要在這個Binding()中使用Bind<介面>.To<介面實作類別>()即可綁定成功;好了為了驗證咋們測試成功性,我們需要在apiController中使用這個依賴關係,這裡我使用建構函式依賴注入的方式:

private readonly IBlogsReposity _reposity  public ValuesController(IBlogsReposity reposity)  {   _reposity = reposity;  }  // GET api/values   public async Task<IEnumerable<MoBlog>> Get(int task = 6)  {   task = task <= 0 ? 6 : task;   task = task > 50 ? 50 : task;   return await _reposity.GetBlogs(task);  }

代碼如上所示,我們運行下程式看下效果:

這個時候提示了個錯誤“沒有預設建構函式”;我們剛才使用的建構函式是帶有參數的,而自訂繼承的 ApiController 中有一個無參數的建構函式,根據錯誤提示內容完全無解;不用擔心,解決這個問題只需要在 WebApiConfig.cs 中Register方法中增加如下代碼:

 //Ninject ioc config.DependencyResolver = NinjectResolverContainer.Current;

這句代碼意思就是讓程式執行上面咋們建立的容器 NinjectResolverContainer ,這樣才能執行到我能剛才寫的ioc程式,才能實現依賴注入;值得注意的是 config.DependencyResolver 是webapi內建的提供的,mvc項目也有同樣提供了 DependencyResolver 給我們使用方便做依賴解析;好了這次我們在運行項目可以得到效果:

» IOC架構Unity的使用

首先,安裝Unity和Unity.WebAPI的nuget包,我這裡的版本是:

我們再同樣建立個自訂容器類 UnityResolverContainer ,實現介面 IDependencyResolver (這裡和上面Ninject一樣);然後這裡貼上具體使用Unity實現的方法:

public class UnityResolverContainer : IDependencyResolver {  private IUnityContainer _container;  public UnityResolverContainer(IUnityContainer container)  {   this._container = container;  }  public IDependencyScope BeginScope()  {   var scopeContainer = this._container.CreateChildContainer();   return new UnityResolverContainer(scopeContainer);  }  /// <summary>  /// 擷取對應類型的執行個體,注意try...catch...不能夠少  /// </summary>  /// <param name="serviceType"></param>  /// <returns></returns>  public object GetService(Type serviceType)  {   try   {    //if (!this._container.IsRegistered(serviceType)) { return null; }    return this._container.Resolve(serviceType);   }   catch   {    return null;   }  }  public IEnumerable<object> GetServices(Type serviceType)  {   try   {    return this._container.ResolveAll(serviceType);   }   catch   {    return new List<object>();   }  }  public void Dispose()  {   if (_container != null)   {    this._container.Dispose();    this._container = null;   }  } }

這裡和使用Ninject的方式很類似,需要注意的是我們在安裝Unity包的時候會自動在 WebApiConfig.cs 增加如下代碼:

 //Unity iocUnityConfig.RegisterComponents();

然後同時在 App_Start 檔案夾中增加 UnityConfig.cs 檔案,我們開啟此檔案能看到一些自動產生的程式碼,這裡我們就可以註冊綁定我們的依賴,代碼如:

public static class UnityConfig {  public static void RegisterComponents()  {   var container = new UnityContainer();   container.RegisterType<IBlogsReposity, BoKeYuan>();   // var lifeTimeOption = new ContainerControlledLifetimeManager();   //container.RegisterInstance<IBlogsReposity>(new BoKeYuan(), lifeTimeOption);   GlobalConfiguration.Configuration.DependencyResolver = new UnityResolverContainer(container);  } }

這裡展示了兩種註冊依賴的方式: container.RegisterType<IBlogsReposity, BoKeYuan>(); 和 container.RegisterInstance<IBlogsReposity>(new BoKeYuan(), lifeTimeOption); ,當然還有其他的擴充方法這裡就不舉例了;最後一句代碼: GlobalConfiguration.Configuration.DependencyResolver = new UnityResolverContainer(container); 和我們之前Ninject代碼一樣,只是換了一個地方和執行個體化寫法方式而已,各位可以仔細對比下;其實 UnityConfig.cs 裡面的內容都可以移到 WebApiConfig.cs 中去,unity自動分開應該是考慮到代碼內容分塊來管理吧,好了同樣我們使用自訂的 ValuesController 的建構函式來添加依賴:

public class ValuesController : ApiController {  private readonly IBlogsReposity _reposity;  public ValuesController(IBlogsReposity reposity)  {   _reposity = reposity;  }  // GET api/values   public async Task<IEnumerable<MoBlog>> Get(int task = 6)  {   task = task <= 0 ? 6 : task;   task = task > 50 ? 50 : task;   return await _reposity.GetBlogs(task);  }}

從代碼上來看,這裡面Ninject和Unity的注入方式沒有差異,這樣能就讓我們開發程式的時候兩種注入方式可以隨便切換了,最後來我這裡提供一個使用這個webapi擷取資料繫結到頁面上的效果:

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.