.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~

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