.Net Framework MVC5以及Web Api2中使用autofac(自动注入,自定义注入,多实现注入,属性注入)

在.Net Framwework MVC5的环境下使用autofac,直接上代码

 

1.我的环境是.Net Framework4.5,MVC5,VS2017

nuget安装autofac:

Install-Package Autofac -version 4.6.2

MVC安装:
Install-Package Autofac.Mvc5 -version 4.0.2

WebApi安装:
Install-Package Autofac.WebApi2 -version 4.3.0

 

基础准备:

标识类:IBaseFlagService(实现该接口的类我们都需要注入进去)

 

用户接口:

    public interface IUserService : IBaseFlagService
    {
        string GetCurrentUserId();

        string FormatDate(DateTime? date, bool isBegin);
    }

用户实现类:

    public class UserService : IUserService
    {
        public string FormatDate(DateTime? date, bool isBegin)
        {
            if (date.HasValue)
            {
                string a = "yyyy-MM-dd ";
                string b = isBegin ? "00:00:00.000" : "23:59:59.999";
                return date.Value.ToString(a + b);
            }
            return null;
        }

        public string GetCurrentUserId()
        {
            return Guid.NewGuid().ToString();
        }
    }

 

动作接口:

    public interface IActionService:IBaseFlagService
    {
        string SayHi();

        string Action();
    }

动作实现类一:猫

    public class CatService : IActionService
    {
        public string Action()
        {
            return "猫咪卖萌!";
        }

        public string SayHi()
        {
            return "喵~";
        }
    }

动作实现类二:狗

    public class DogService : IActionService
    {
        public string Action()
        {
            return "憨憨的柯基卖萌!";
        }

        public string SayHi()
        {
            return "汪汪汪~";
        }
    }

 

在global程序启动时注入autofac:

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            IocService.InitAutofac();
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }

IocService:

    public class IocService
    {
        public static IContainer Container;

        public static void InitAutofac()
        {
            string dllNameStr = "WebMvcUseAutofac,WebMvcUseAutofacServices";
            string a = ",";
            var assList = dllNameStr.Split(new string[] { a }, StringSplitOptions.RemoveEmptyEntries).Select(r => Assembly.Load(r)).ToArray();

            var baseType = typeof(IBaseFlagService);

            var builder = new ContainerBuilder();

            //RegisterAuto(builder, assList, baseType);
            RegisterCustom(builder, assList, baseType);
            RegisterWithMultipleImplements(builder);

            builder.RegisterControllers(assList).PropertiesAutowired();//Mvc使用  注意:控制器无法单例注入,必须一次请求,一个实例,无法单例
            //builder.RegisterApiControllers(assList).PropertiesAutowired();//WebApi使用,同样,控制器无法单例注入

            IocService.Container = builder.Build();

            DependencyResolver.SetResolver(new AutofacDependencyResolver(IocService.Container));//Mvc使用
            //GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(IocService.Container);//WebApi使用
        }

        /// <summary>
        /// 通过注入,将实现IBaseFlagService接口的所有服务类注入到类本身所实现的接口中
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assList"></param>
        /// <param name="baseType"></param>
        private static void RegisterAuto(ContainerBuilder builder, Assembly[] assList, Type baseType)
        {
            builder.RegisterAssemblyTypes(assList).Where(r => baseType.IsAssignableFrom(r) && r.IsInterface == false)//找到程序集中符合条件的类
                .AsSelf().AsImplementedInterfaces()//注入到自己实现的接口中
                .SingleInstance()//生命周期:单例
                .PropertiesAutowired();//支持属性注入
        }

        /// <summary>
        /// 自己写逻辑注入
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assList"></param>
        /// <param name="baseType"></param>
        private static void RegisterCustom(ContainerBuilder builder, Assembly[] assList, Type baseType)
        {
            //程序集下所有的类
            var allTypeList = assList.SelectMany(r => r.GetTypes()).ToList();
            var groupTypeList = allTypeList.ToLookup(r => r.Name).Select(r => new { Name = r.Key, Count = r.Count(), List = r.ToArray() }).OrderBy(r => r.Count).ToArray();
            //实现了指定接口的类
            var allServiceTypeList = allTypeList.FindAll(r => baseType.IsAssignableFrom(r));
            //服务类
            var serviceTypes = allServiceTypeList.FindAll(r => r.IsInterface == false);
            //服务接口(排除掉标签接口)
            var iServiceTypes = allServiceTypeList.FindAll(r => r.IsInterface && IsSameType(r, baseType) == false);
            string a = ",";
            foreach (var serviceType in serviceTypes)
            {
                //该服务类所实现的接口
                var interfaceList = serviceType.GetInterfaces();

                var useInterfaceList = interfaceList.Intersect(iServiceTypes).ToArray();

                //校验
                if (useInterfaceList.Length == 0)
                    throw new Exception($"服务类{serviceType.Name}没有实现任何接口!");
                else if (useInterfaceList.Length > 1)
                    throw new Exception($"服务类{serviceType.Name}实现的接口数量大于1个:{string.Join(a, useInterfaceList.Select(r => r.Name))}");

                //注入操作
                builder.RegisterType(serviceType).As(useInterfaceList[0])
                    .SingleInstance()//单例注入
                    .PropertiesAutowired();//支持属性注入
            }
        }

        /// <summary>
        /// 一个接口多个实现,手动注入(也可以自动注入,通过增加特性来标识,然后读取注入,我这里就不做演示)
        /// </summary>
        /// <param name="builder"></param>
        private static void RegisterWithMultipleImplements(ContainerBuilder builder)
        {
            builder.RegisterType<CatService>().Named<IActionService>("Cat").PropertiesAutowired();//Named参数只能是string
            builder.RegisterType<DogService>().Keyed<IActionService>("Dog").PropertiesAutowired();//这里只是使用Keyed,因为Keyed参数是object,可以使用枚举
        }

        public static bool IsSameType(Type type1, Type type2)
        {
            return type1.FullName == type2.FullName;
        }
    }

 

测试代码:

    public class HomeController : Controller
    {
        //构造函数注入
        public IUserService _UserServiceForConstructor;

        public HomeController(IUserService userService)
        {
            this._UserServiceForConstructor = userService;
        }

        public IUserService _UserServiceForProperty { get; set; }

        public ActionResult Index()
        {
            //使用构造函数注入的接口
            string dateStr = _UserServiceForConstructor.FormatDate(DateTime.Now, false);
            //使用属性函数注入的接口
            string userId = _UserServiceForProperty.GetCurrentUserId();

            var catService = IocService.Container.ResolveNamed<IActionService>("Cat");
            string catStr = catService.SayHi();
            var dogService = IocService.Container.ResolveKeyed<IActionService>("Dog");
            string dogStr = dogService.SayHi();

            string a = ";";
            ViewBag.PageData = string.Join(a, new List<string>() { dateStr, userId, catStr, dogStr });
            return View();
        }
    }

前端:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title></title>
</head>
<body>
    <div>
        @ViewBag.PageData
    </div>
</body>
</html>

运行结果:

Ending~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章