webapi中如何使用依賴注入
本篇將要和大家分享的是webapi中如何使用依賴注入,依賴注入這個東西在接口中常用,實際工作中也用的比較頻繁,因此這里分享兩種在api中依賴注入的方式Ninject和Unity;由于快過年這段時間打算了解下vue.js,所以后面對webapi的分享文章可能會慢點更新,希望支持的朋友們多多諒解,畢竟只有不斷充電學習,才能更好的適應(yīng)it行業(yè)吧;本章內(nèi)容希望大家喜歡,也希望各位多多掃碼支持和推薦謝謝:
» Task并行任務(wù)抓取博客園首頁信息
» IOC框架Ninject的使用
» IOC框架Unity的使用
下面一步一個腳印的來分享:
» Task并行任務(wù)抓取博客園首頁信息
首先,咋們需要創(chuàng)建一個博客信息實體類 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>
/// 點贊次數(shù)
/// </summary>
public int ZanNum { get; set; }
/// <summary>
/// 閱讀次數(shù)
/// </summary>
public int ReadNum { get; set; }
/// <summary>
/// 評論次數(shù)
/// </summary>
public int CommiteNum { get; set; }
/// <summary>
/// 創(chuàng)建時間
/// </summary>
public DateTime CreateTime { get; set; }
}
然后,需要創(chuàng)建一個接口 IBlogsReposity ,并且定義一個如下代碼的方法:
public interface IBlogsReposity
{
/// <summary>
/// 獲取博客信息
/// </summary>
/// <param name="nTask"></param>
/// <returns></returns>
Task<IEnumerable<MoBlog>> GetBlogs(int nTask);
}
注意這里定義的返回類型是Task<T>,主要作用是async異步返回博客信息,并且方便使用并行方式抓取不同頁數(shù)的數(shù)據(jù),因此這里傳遞了一個int類型的參數(shù)nTask(表示任務(wù)數(shù)量);好了咋們來一起看下具體實現(xiàn)接口的 BoKeYuan 類里面的代碼:
public class BoKeYuan : IBlogsReposity
{
public async Task<IEnumerable<MoBlog>> GetBlogs(int nTask)
{
var blogs = new List<MoBlog>();
try
{
//開啟nTask個任務(wù),讀取前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">頁數(shù)</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]作為并行任務(wù)的容器;
2. Task.Factory.StartNew創(chuàng)建對應(yīng)的任務(wù)
3. Task.WaitAll(tasks, TimeSpan.FromSeconds(30));等待容器里面任務(wù)完成30秒后超時
4. 最后通過把item.Result任務(wù)結(jié)果添加到集合中,返回我們需要的數(shù)據(jù)
這里解析博客內(nèi)容信息用的正則表達式,這種方式在抓取一定內(nèi)容上很方便;群里面有些朋友對正則有點反感,剛接觸的時候覺得挺不好寫的,所以一般都采用更復(fù)雜或者其他的解析方式來獲取想要的內(nèi)容,這里提出來主要是和這些朋友分享下正則獲取數(shù)據(jù)是多么方便,很有必要學習下并且掌握常規(guī)的用法,這也是一種苦盡甘來的體驗吧哈哈;
好了咋們創(chuàng)建一個webapi項目取名為 Stage.Api ,使用她自動生成的 ValuesController 文件里面的Get方法接口來調(diào)用咋們上面實現(xiàn)的博客抓取方法,代碼如下:
// 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(); 來創(chuàng)建和調(diào)用具體的實現(xiàn)類,這里貼出一個線上抓取博客首頁信息的地址(不要告訴dudu):http://www.lovexins.com:1001/api/values?task=6;咋們來想象一下,如果這個Get方法中還需要調(diào)用其他實現(xiàn)了接口 IBlogsReposity 的博客抓取類,那咋們又需要手動new一次來創(chuàng)建對應(yīng)的對象;倘若除了在 ValuesController.cs 文件中調(diào)用了博客數(shù)據(jù)抓取,其他文件還需要這抓取數(shù)據(jù)的業(yè)務(wù),那么又會不停的new,可能有朋友就會說那弄一個工廠模式怎么樣,不錯這是可行的一種方式,不過這里還有其他方法能處理這種問題,比如:ioc依賴注入;因此就有了下面的分享內(nèi)容。
» IOC框架Ninject的使用
首先,我們要使用ninject需要使用nuget下載安裝包,這里要注意的是Ninject版本比較多,需要選擇合適自己webapi的版本,我這里選擇的是:

看起來很老了哈哈,不過咋們能用就行,安裝起來可能需要點時間,畢竟比較大么也有可能是網(wǎng)絡(luò)的問題吧;安裝完后咋們創(chuàng)建一個自定義類 NinjectResolverScope 并實現(xiàn)接口 IDependencyScope , IDependencyScope 對應(yīng)的類庫是 System.Web.Http.dll (注:由于webapi2項目自動生成時候可能勾選了mvc,mvc框架里面也包含了一個IDependencyScope,所以大家需要注意區(qū)分下),好了咋們來直接看下 NinjectResolverScope 實現(xiàn)代碼:
/// <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() 包住,經(jīng)過多方調(diào)試和測試,這里面會執(zhí)行除手動bind綁定外的依賴,還會執(zhí)行幾個其他非手動綁定的實例對象,這里使用try避免拋異常影響到程序(其實咋們可以在這里用代碼過濾掉非手動綁定的幾個實例);這里也簡單說下這個 NinjectResolverScope 中方法執(zhí)行的先后順序:GetService=》GetServices=》Dispose,GetService主要用來獲取依賴注入對象的實例;好了到這里咋們還需要一個自定義容器類 NinjectResolverContainer ,該類繼承自上面的 NinjectResolverScope 和實現(xiàn) IDependencyResolver 接口(其實細心的朋友能發(fā)現(xiàn)這個 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>
/// 開始執(zhí)行
/// </summary>
/// <returns></returns>
public IDependencyScope BeginScope()
{
return new NinjectResolverScope(this.kernel.BeginBlock());
}
}
這里能夠看到 IKernel kernel = new StandardKernel(); 這代碼,她們引用都來源于我們安裝的Ninject包,通過調(diào)用初始化Initing()后,我們需要在Binding()方法中手動綁定我們對應(yīng)需要依賴注入的實例,Ninject綁定方式有很多種這里我用的格式是: kernel.Bind<接口>().To<實現(xiàn)類>(); 如此簡單就實現(xiàn)了依賴注入,每次我們需要添加不同的依賴項的時候只需要在這個Binding()中使用Bind<接口>.To<接口實現(xiàn)類>()即可綁定成功;好了為了驗證咋們測試成功性,我們需要在apiController中使用這個依賴關(guān)系,這里我使用構(gòu)造函數(shù)依賴注入的方式:
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);
}
代碼如上所示,我們運行下程序看下效果:

這個時候提示了個錯誤“沒有默認構(gòu)造函數(shù)”;我們剛才使用的構(gòu)造函數(shù)是帶有參數(shù)的,而自定義繼承的 ApiController 中有一個無參數(shù)的構(gòu)造函數(shù),根據(jù)錯誤提示內(nèi)容完全無解;不用擔心,解決這個問題只需要在 WebApiConfig.cs 中Register方法中增加如下代碼:
//Ninject ioc config.DependencyResolver = NinjectResolverContainer.Current;
這句代碼意思就是讓程序執(zhí)行上面咋們創(chuàng)建的容器 NinjectResolverContainer ,這樣才能執(zhí)行到我能剛才寫的ioc程序,才能實現(xiàn)依賴注入;值得注意的是 config.DependencyResolver 是webapi自帶的提供的,mvc項目也有同樣提供了 DependencyResolver 給我們使用方便做依賴解析;好了這次我們在運行項目可以得到如圖效果:

» IOC框架Unity的使用
首先,安裝Unity和Unity.WebAPI的nuget包,我這里的版本是:

我們再同樣創(chuàng)建個自定義容器類 UnityResolverContainer ,實現(xiàn)接口 IDependencyResolver (這里和上面Ninject一樣);然后這里貼上具體使用Unity實現(xiàn)的方法:
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>
/// 獲取對應(yīng)類型的實例,注意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 ioc UnityConfig.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 里面的內(nèi)容都可以移到 WebApiConfig.cs 中去,unity自動分開應(yīng)該是考慮到代碼內(nèi)容分塊來管理吧,好了同樣我們使用自定義的 ValuesController 的構(gòu)造函數(shù)來添加依賴:
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的注入方式?jīng)]有差異,這樣能就讓我們開發(fā)程序的時候兩種注入方式可以隨便切換了,最后來我這里提供一個使用這個webapi獲取數(shù)據(jù)綁定到頁面上的效果:

以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持腳本之家!
相關(guān)文章
.NET使用NPOI實現(xiàn)讀取帶有圖片的excel數(shù)據(jù)
這篇文章主要為大家詳細介紹了.NET如何使用NPOI實現(xiàn)讀取帶有圖片的excel數(shù)據(jù),文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-03-03
ASP.NET Core如何實現(xiàn)簡單的靜態(tài)網(wǎng)站滾動更新
這篇文章主要給大家介紹了關(guān)于ASP.NET Core如何實現(xiàn)簡單的靜態(tài)網(wǎng)站滾動更新的相關(guān)資料,文中給出了詳細實現(xiàn)的代碼,對需要的朋友來說很實用,需要的朋友可以參考下2021-07-07
獲取asp.net服務(wù)器控件的客戶端ID和Name的實現(xiàn)方法
下面小編就為大家?guī)硪黄@取asp.net服務(wù)器控件的客戶端ID和Name的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-05-05
Microsoft SQL Server 2005 Express 遠程訪問設(shè)置詳述,100%成功篇
Microsoft SQL Server 2005 Express Edition是Microsoft數(shù)據(jù)庫的低端解決方案,是免費的,并且可以隨軟件免費發(fā)布,而就其數(shù)據(jù)庫功能對于一般的企業(yè)級應(yīng)用已足夠了。但 默認安裝時只允許本地訪問,而不能遠程訪問。2009-03-03
.NET Core應(yīng)用類型(Portable apps & Self-contained apps)
這篇文章主要介紹了.NET Core應(yīng)用類型,通常類型用來描述一個特定的執(zhí)行模型或者基于此的應(yīng)用,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
數(shù)據(jù)庫 數(shù)據(jù)類型float到C#類型decimal, float數(shù)據(jù)類型轉(zhuǎn)化無效
數(shù)據(jù)庫 數(shù)據(jù)類型float到C#類型decimal, float數(shù)據(jù)類型轉(zhuǎn)化無效的解決方法2009-07-07
asp.net 頁面轉(zhuǎn)向 Response.Redirect, Server.Transfer, Server.Exec
如果你讀過很多行業(yè)雜志和 ASP.NET 示例,你會發(fā)現(xiàn),大多數(shù)人使用 Response.Redirect 將用戶引導(dǎo)到另一個頁面,而另一些人好像偏愛于神秘的 Server.Transfer,那么,這二者有什么區(qū)別?2009-11-11
ASP.NET中GridView和Repeater重復(fù)數(shù)據(jù)如何合并
這篇文章主要介紹了ASP.NET中GridView和Repeater重復(fù)數(shù)據(jù)合并的方法,感興趣的小伙伴們可以參考一下2016-08-08

