IOC控制反转--WebApi整合Unity

WebApi 整合IOC Unity

新建接口文件IUserService:

namespace SOA.Interface
{
    public interface IUserService
    {
        string Query();
    }
}

新建实现类文件UserService:

namespace SOA.Service
{
    public class UserService : IUserService
    {
        public string Query()
        {
            return JsonConvert.SerializeObject(new { 
                Id=123,
                Name ="陈贺章",
                Description = "VIP用户"
            });
        }
    }
}

小白

新建控制器UserController,最简单最常规的方式就是实例化类调用方法:

namespace SOA.WebApi.Controllers
{
    public class UserController : ApiController
    {
        public string GetUser() 
        {
            IUserService service = new UserService();
            return service.Query();
        }
    }
}

高手

因为我们这里用到了接口IUserService,所以我们最好能通过容器实现,.net 最常用的就是Unity

引入Unity所需程序包:Unity、Unity.Interception、Unity.Abstractions、Unity.Interception.Configuration、Unity.WebApi

image-20220301204601677

新建配置文件 /CfgFiles/Unity.Config

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
  </configSections>
  <unity>
    <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
    <containers>
      <container name="webApiContainer">
		  <!--SOA.Interface.IUserService 指向 SOA.Service.UserService-->
		  <register type="SOA.Interface.IUserService,SOA.Interface" mapTo="SOA.Service.UserService, SOA.Service"/>
      </container>
    </containers>
  </unity>
</configuration>

新建 /Utility/ContainerFactory(简单工厂+配置文件+反射),读取配置文件初始化容器:

namespace SOA.WebApi.Utility
{
    public class ContainerFactory
    {
        private static IUnityContainer _UnityContainer = null;

        /// <summary>
        /// 通过静态构造函数初始化Unity容器 
        /// 执行且只执行一次
        /// </summary>
        static ContainerFactory()
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找配置文件的路径
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
            IUnityContainer container = new UnityContainer();
            section.Configure(container, "webApiContainer");    //读取配置文件中的“webApiContainer”,不能乱写
            _UnityContainer = container;
        }

        public static IUnityContainer BuildContainer()
        {
            return _UnityContainer;
        }
    }
}

经过这两个步骤之后,我们就能很轻松获取到容器了,相对应的我们可以修改一下Controller查看下效果:

namespace SOA.WebApi.Controllers
{
    public class UserController : ApiController
    {
        public string GetUser() 
        {
            //IUserService service = new UserService();
            //return service.Query();

            //获取容器
            var container = ContainerFactory.BuildContainer();
            IUserService service = container.Resolve<IUserService>();   //需要引入using Unity
            return service.Query();
        }
    }
}

效果:

<string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">{"Id":123,"Name":"陈贺章","Description":"VIP用户"}</string>

大神

尽管我们使用的静态构造,但是每次都需要找容器,因此我们可以使用构造函数注入:

namespace SOA.WebApi.Controllers
{
    public class UserController : ApiController
    {
        private IUserService _IUserService = null;
        //构造函数注入
        public UserController(IUserService service) {
            _IUserService = service;
        }

        public string GetUser() 
        {
            return _IUserService.Query();
        }
    }
}

但是这样直接启动访问会报错,因为控制器是由控制器默认工厂创建,增加了带参数的构造函数以后,默认的控制器工厂无法创建控制器,所以可以让Unity来创建控制

自定义 DependencyResolver 继承自 IDependencyResolver接口,实现接口:

namespace SOA.WebApi.Utility
{
    public class CustomDependencyResolver : IDependencyResolver
    { 
        private static IUnityContainer unityContainer = null;

        static CustomDependencyResolver()
        {
            unityContainer= ContainerFactory.BuildContainer();
        }

        /// <summary>
        /// 创建一个子容器(指定作用域时)
        /// </summary>
        /// <returns></returns>
        public IDependencyScope BeginScope()
        {
            return new UnityDependencyResolver(unityContainer.CreateChildContainer());
        }

        public void Dispose()
        {
            this.Dispose();
        }

        public object GetService(Type serviceType)
        {
            //获取创建的实例,因为不是所有东西都通过IOC注入了(会包含一些系统自带的东西),所以需要try catch,返回null
            try
            {
                return unityContainer.Resolve(serviceType);
            }
            catch (Exception ex)
            {
                return null;
            } 
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            //获取创建的实例,因为不是所有东西都通过IOC注入了(会包含一些系统自带的东西),所以需要try catch,返回null
            try
            {
                return unityContainer.ResolveAll(serviceType);
            }
            catch (Exception ex)
            {
                return null;
            } 
        }
    }
}

修改WebApiConfig 文件,替换系统框架中的工厂:

config.DependencyResolver = new CustomDependencyResolver(); //替换系统框架中的工厂
//config.DependencyResolver = new UnityDependencyResolver(ContainerFactory.BuildContainer());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武功山上捡瓶子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值