本篇将要和大家分享的是webapi中如何使用依赖注入,依赖注入这个东西在接口中常用,实际工作中也用的比较频繁,因此这里分享两种在api中依赖注入的方式NinjectUnity;由于快过年这段时间打算了解下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 = ; i <= tasks.Length; i++)
{
tasks[i - ] = await Task.Factory.StartNew<Task<IEnumerable<MoBlog>>>((page) =>
{ return GetBlogsByPage(Convert.ToInt32(page));
}, i);
} //30s等待
Task.WaitAll(tasks, TimeSpan.FromSeconds()); 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 <= ) { 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任务结果添加到集合中,返回我们需要的数据

这里解析博客内容信息用的正则表达式,这种方式在抓取一定内容上很方便;群里面有些朋友对正则有点反感,刚接触的时候觉得挺不好写的,所以一般都采用更复杂或者其他的解析方式来获取想要的内容,这里提出来主要是和这些朋友分享下正则获取数据是多么方便,很有必要学习下并且掌握常规的用法,这也是一种苦尽甘来的体验吧哈哈;

好了咋们创建一个webapi项目取名为 Stage.Api ,使用她自动生成的 ValuesController 文件里面的Get方法接口来调用咋们上面实现的博客抓取方法,代码如下:

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

这里使用 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 实现代码:

 /// <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 = )
{
task = task <= ? : task;
task = task > ? : 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 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 里面的内容都可以移到 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 = )
{
task = task <= ? : task;
task = task > ? : task;
return await _reposity.GetBlogs(task);
}
}

从代码上来看,这里面Ninject和Unity的注入方式没有差异,这样能就让我们开发程序的时候两种注入方式可以随便切换了,最后来我这里提供一个使用这个webapi获取数据绑定到页面上的效果:

外网浏览地址:http://www.lovexins.com:1001/home,本章的分享内容就到这里,希望能给大家带来帮助,也希望大家不吝点“推荐”,谢谢。

webapi - 使用依赖注入的更多相关文章

  1. webapi框架搭建-依赖注入之autofac

    前言 c#的依赖注入框架有unity.autofac,两个博主都用过,感觉unity比较简单而autofac的功能相对更丰富(自然也更复杂一点),本篇将基于前几篇已经创建好的webapi项目,引入au ...

  2. AutoFac实现WebAPI依赖注入(EF以及Mysql)

    什么是依赖注入? 我们以实际的例子来加以介绍 实体如下 public class Product { public int ID { get; set; } public string Name { ...

  3. 在MVC5和webAPI下是用Autofac依赖注入

    很多书本中都提到依赖注入,控制反转等概念,这些都是为了实现松耦合层.组件和类目的. 常见的是使用Repository类分离Controller和Model的直接联系.而为了解除Repository类和 ...

  4. WebApi中使用Ninject 依赖注入

    之前Ninject依赖注入是在MVC中使用,最近在WebApi中使用,用之前的MVC方式发现使用接口注入,一直是Null错误,网上查询了一些资源,总结一下,以后备用. 主要分为以下几步骤: 在NuGe ...

  5. 第七节:WebApi与Unity整合进行依赖注入和AOP的实现

    一. IOC和DI 1. 通过Nuget引入Unity程序集. PS:[版本:5.8.6] 2. 新建DIFactory类,用来读取Unity的配置文件并创建Unity容器,需要注意的是DIFacto ...

  6. WebAPi使用Autofac实现依赖注入

    WebAPi依赖注入  使用记录 笔记 1.NuGet包安装 2.控制器加入构造函数 3.Global.asax  ----Application_Start 应用程序启动时 using Autofa ...

  7. NetCore+Dapper WebApi架构搭建(四):仓储的依赖注入

    上一节我们讲到实体,仓储接口和仓储接口的实现需要遵循约定的命名规范,不仅是规范,而且为了依赖注入,现在我们实现仓储的依赖注入 在NetCore WebApi项目中新添加一个文件夹(Unit),当然你也 ...

  8. 使用react全家桶制作博客后台管理系统 网站PWA升级 移动端常见问题处理 循序渐进学.Net Core Web Api开发系列【4】:前端访问WebApi [Abp 源码分析]四、模块配置 [Abp 源码分析]三、依赖注入

    使用react全家桶制作博客后台管理系统   前面的话 笔者在做一个完整的博客上线项目,包括前台.后台.后端接口和服务器配置.本文将详细介绍使用react全家桶制作的博客后台管理系统 概述 该项目是基 ...

  9. Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor

    Webservice WCF WebApi   注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...

随机推荐

  1. [Spring]IoC容器之进击的注解

    先啰嗦两句: 第一次在博客园使用markdown编辑,感觉渲染样式差强人意,还是github的样式比较顺眼. 概述 Spring2.5 引入了注解. 于是,一个问题产生了:使用注解方式注入 JavaB ...

  2. android自定义控件一站式入门

    自定义控件 Android系统提供了一系列UI相关的类来帮助我们构造app的界面,以及完成交互的处理. 一般的,所有可以在窗口中被展示的UI对象类型,最终都是继承自View的类,这包括展示最终内容的非 ...

  3. ASP.NET Aries 入门开发教程2:配置出一个简单的列表页面

    前言: 朋友们都期待我稳定地工作,但创业公司若要躺下,也非意念可控. 若人生注定了风雨飘摇,那就雨中前行了. 最机开始看聊新的工作机会,欢迎推荐,创业公司也可! 同时,趁着自由时间,抓紧把这系列教程给 ...

  4. static,你还敢用吗?(二)

    为了压系统,昨天小组在测试环境模拟了一大批订单数据.今天上午查看记录的账单计息日志,发现了一大堆的MySqlException MySql.Data.MySqlClient.MySqlExceptio ...

  5. 逆天Kali带你游遍大江南北~安全之前人铺路!

    0.Linux基础学习(基本指令) http://www.cnblogs.com/dunitian/p/4822807.html 1.Kali安装到移动硬盘或者U盘中~Linux系列通用方法(包括An ...

  6. 按需加载.js .css文件

    首先,理解按需加载当你需要用到某个js里面的函数什么鬼,或者某个css里的样式的时候你才开始加载这个文件. 然后是怎样实现的,简单来说就是在js中动态的createElem<script> ...

  7. jQuery学习之路(6)- 简单的表格应用

    ▓▓▓▓▓▓ 大致介绍 在CSS技术之前,网页的布局基本都是依靠表格制作,当有了CSS之后,表格就被很多设计师所抛弃,但是表格也有他的用武之地,比如数据列表,下面以表格中常见的几个应用来加深对jQue ...

  8. SQL 数据优化索引建suo避免全表扫描

    首先什么是全表扫描和索引扫描?全表扫描所有数据过一遍才能显示数据结果,索引扫描就是索引,只需要扫描一部分数据就可以得到结果.如果数据没建立索引. 无索引的情况下搜索数据的速度和占用内存就会比用索引的检 ...

  9. Linux Socket 原始套接字编程

    对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...

  10. Visual Studio Code 配置指南

    Visual Studio Code (简称 VS Code)是由微软研发的一款免费.开源的跨平台文本(代码)编辑器.在我看来它是「一款完美的编辑器」. 本文是有关 VS Code 的特性介绍与配置指 ...