本篇将要和大家分享的是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; }
}
</div>
然后,需要创建一个接口 IBlogsReposity ,并且定义一个如下代码的方法:
public interface IBlogsReposity
{
/// <summary>
/// 获取博客信息
/// </summary>
/// <param name="nTask"></param>
/// <returns></returns>
Task<IEnumerable<MoBlog>> GetBlogs(int nTask);
}
</div>
注意这里定义的返回类型是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;
}
}
</div>
代码分析:
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任务结果添加到集合中,返回我们需要的数据
这里解析博客内容信息用的正则表达式,这种方式在抓取一定内容上很方便;群里面有些朋友对正则有点反感,刚接触的时候觉得挺不好写的,所以一般都采用更复杂或者其他的解析方式来获取想要的内容,这里提出来主要是和这些朋友分享下正则获取数据是多么方便,很有必要学习下并且掌握常规的用法,这也是一种苦尽甘来的体验吧哈哈;
好了咋们创建一个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);
}
</div>
这里使用 IBlogsReposity _reposity = new BoKeYuan(); 来创建和调用具体的实现类,这里贴出一个线上抓取博客首页信息的地址(不要告诉dudu):http://www.lovexins.com: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 实现代码:

