C# IoC学习笔记
程序员文章站
2022-06-22 09:59:57
一、引言 面向接口(抽象)编程,是为了降低程序的耦合度,符合依赖倒置原则。因此典型的三层架构UI、BLL、DAL基于接口设计后,会拓展成UI、IBLL、BLL、IDAL、DAL。在上一篇《C# IoC学习笔记》中我们可以了解到,控制反转(IoC)使对象的创建交给了第三方IoC容器如Unity。利用U ......
一、引言
面向接口(抽象)编程,是为了降低程序的耦合度,符合依赖倒置原则。因此典型的三层架构ui、bll、dal基于接口设计后,会拓展成ui、ibll、bll、idal、dal。在上一篇《c# ioc学习笔记》中我们可以了解到,控制反转(ioc)使对象的创建交给了第三方ioc容器如unity。利用unity的ioc功能,可以对基于接口设计的三层架构做进一步的升级,搭建一个更容易实现的可配置可扩展的三层架构;利用unity的aop功能,使框架更加的简洁,因为它抽出了框架的公共逻辑部分。
二、项目建立
2.1、项目建立
依次新建项目ui(client)、ibll、bll、idal、dal、model、common。
2.2项目说明
三、项目之间的引用关系
3.1、对着项目名称右键->添加->引用->项目,添加各个项目的引用。
3.2、引用说明
四、项目需安装的nuget包
五、注意事项
对unity容器的ioc调用进行封装,container应封装成单例模式以提高效率,此处使用memorycache。
5.1、在common项目引用system.runtime.caching.dll,并在helper文件夹下新建一个缓存帮助类:memorycachehelper.cs。
/// <summary> /// 内存缓存帮助类,支持绝对过期时间、滑动过期时间、文件依赖三种缓存方式。 /// </summary> class memorycachehelper { private static readonly object _locker1 = new object(), _locker2 = new object(); /// <summary> /// 取缓存项,如果不存在则返回空。 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="key"></param> /// <returns></returns> public static t getcacheitem<t>(string key) { try { return (t)memorycache.default[key]; } catch { return default(t); } } /// <summary> /// 是否包含指定键的缓存项 /// </summary> /// <param name="key"></param> /// <returns></returns> public static bool contains(string key) { return memorycache.default.contains(key); } /// <summary> /// 取缓存项,如果不存在则新增缓存项。 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="key"></param> /// <param name="cachepopulate"></param> /// <param name="slidingexpiration"></param> /// <param name="absoluteexpiration"></param> /// <returns></returns> public static t getoraddcacheitem<t>(string key, func<t> cachepopulate, timespan? slidingexpiration = null, datetime? absoluteexpiration = null) { if (string.isnullorwhitespace(key)) throw new argumentexception("invalid cache key"); if (cachepopulate == null) throw new argumentnullexception("cachepopulate"); if (slidingexpiration == null && absoluteexpiration == null) throw new argumentexception("either a sliding expiration or absolute must be provided"); if (memorycache.default[key] == null) { lock (_locker1) { if (memorycache.default[key] == null) { t cachevalue = cachepopulate(); if (!typeof(t).isvaluetype && cachevalue == null) //如果是引用类型且为null则不存缓存 { return cachevalue; } var item = new cacheitem(key, cachevalue); var policy = createpolicy(slidingexpiration, absoluteexpiration); memorycache.default.add(item, policy); } } } return (t)memorycache.default[key]; } /// <summary> /// 取缓存项,如果不存在则新增缓存项。 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="key"></param> /// <param name="cachepopulate"></param> /// <param name="dependencyfilepath"></param> /// <returns></returns> public static t getoraddcacheitem<t>(string key, func<t> cachepopulate, string dependencyfilepath) { if (string.isnullorwhitespace(key)) throw new argumentexception("invalid cache key"); if (cachepopulate == null) throw new argumentnullexception("cachepopulate"); if (memorycache.default[key] == null) { lock (_locker2) { if (memorycache.default[key] == null) { t cachevalue = cachepopulate(); if (!typeof(t).isvaluetype && cachevalue == null) //如果是引用类型且为null则不存缓存 { return cachevalue; } var item = new cacheitem(key, cachevalue); var policy = createpolicy(dependencyfilepath); memorycache.default.add(item, policy); } } } return (t)memorycache.default[key]; } /// <summary> /// 指定缓存项的一组逐出和过期详细信息 /// </summary> /// <param name="slidingexpiration"></param> /// <param name="absoluteexpiration"></param> /// <returns></returns> private static cacheitempolicy createpolicy(timespan? slidingexpiration, datetime? absoluteexpiration) { var policy = new cacheitempolicy(); if (absoluteexpiration.hasvalue) { policy.absoluteexpiration = absoluteexpiration.value; } else if (slidingexpiration.hasvalue) { policy.slidingexpiration = slidingexpiration.value; } policy.priority = cacheitempriority.default; return policy; } /// <summary> /// 指定缓存项的一组逐出和过期详细信息 /// </summary> /// <param name="filepath"></param> /// <returns></returns> private static cacheitempolicy createpolicy(string filepath) { cacheitempolicy policy = new cacheitempolicy(); policy.changemonitors.add(new hostfilechangemonitor(new list<string>() { filepath })); policy.priority = cacheitempriority.default; return policy; } /// <summary> /// 移除指定键的缓存项 /// </summary> /// <param name="key"></param> public static void removecacheitem(string key) { if (contains(key)) { memorycache.default.remove(key); } } }
5.2、在common项目helper文件夹下面新建一个unity帮助类:unityhelper.cs,并实现container的缓存。
/// <summary> /// unity容器帮助类 /// </summary> public static class unityhelper { /// <summary> /// unity容器创建对象(不含别名) /// </summary> /// <param name="containername">容器名称</param> /// <returns></returns> public static t getobject<t>(string containername) { iunitycontainer container = memorycachehelper.getoraddcacheitem(containername, () => { iunitycontainer unitycontainer = new unitycontainer(); execonfigurationfilemap filemap = new execonfigurationfilemap { execonfigfilename = path.combine(appdomain.currentdomain.basedirectory + @"configfiles\unity.config") }; configuration configuration = configurationmanager.openmappedexeconfiguration(filemap, configurationuserlevel.none); unityconfigurationsection configsection = (unityconfigurationsection)configuration.getsection(unityconfigurationsection.sectionname); configsection.configure(unitycontainer, containername); return unitycontainer; },timespan.fromminutes(30),null); return container.resolve<t>(); } /// <summary> /// unity容器创建对象(含别名) /// </summary> /// <typeparam name="t"></typeparam> /// <param name="containername">容器名称</param> /// <param name="alisname">对象别名</param> /// <returns></returns> public static t getobject<t>(string containername, string alisname) { iunitycontainer container = memorycachehelper.getoraddcacheitem(containername, () => { iunitycontainer unitycontainer = new unitycontainer(); execonfigurationfilemap filemap = new execonfigurationfilemap { execonfigfilename = path.combine(appdomain.currentdomain.basedirectory + @"configfiles\unity.config") }; configuration configuration = configurationmanager.openmappedexeconfiguration(filemap, configurationuserlevel.none); unityconfigurationsection configsection = (unityconfigurationsection)configuration.getsection(unityconfigurationsection.sectionname); configsection.configure(unitycontainer, containername); return unitycontainer; }, timespan.fromminutes(30), null); return container.resolve<t>(alisname); } }
推荐阅读