zoukankan      html  css  js  c++  java
  • 实战篇

    实战篇

    上一篇《我在项目中运用 IOC(依赖注入)--入门篇》只是简单的使用 IOC。实际项目使用 IOC 的情景复杂多了,比如说,构造函数有多个参数,有多个类继承同一个接口... Unity都有解决方法。首先回顾一下入门篇的项目需求:项目中数据统计功能,它下面有三种不同的统计类型,需要与数据库交互,然后展示到页面,在这篇中我们接着这个需求继续扩充。

    【没有接口】

    新增Model 层,LoginUser 当前登录人。无接口的怎样用IOC 创建对象。代码如下

    Model.LoginUser loginUser = container.Resolve<Model.LoginUser>();

    【多个子类】

    DAL 层 新增ShowResult2 方法

    复制代码
    public class Analyse:IDAL.IAnalyse
    {
    public void ShowResult()
    {
    Console.WriteLine("分析底层数据库交互");
    }
    
    public void ShowResult2()
    {
    Console.WriteLine("这是B类分析底层数据库交互");
    }
    }
    复制代码

    BLL层 新增 AnalyseB ,继承 IAnalyse

    复制代码
     public class AnalyseB:IBLL.IAnalyse
        {
            ////使用依赖注入
            [Dependency]
            public IDAL.IAnalyse dal { get; set; }
    
            public void ShowResult()
            {
                dal.ShowResult2();
            }
        }
    复制代码

    按照入门篇的步骤,需要在core 层 DependencyRegister 修改 DependencyRegisterContainer 方法

    复制代码
    public static IUnityContainer DependencyRegisterContainer()
            {
                IUnityContainer container = new UnityContainer();
                container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
                         .RegisterType<IDAL.IAnalyse, DAL.Analyse>()
                         .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>();
                return container;
            }
    复制代码

    我们发现IBLL.IAnalyse被两个类继承,所以在 IOC 容器中注入了两次。这样写能区分开吗?我们先在UI 层增加显示代码

    复制代码
    /// <summary>
            /// 多个类继承同一个接口
            /// </summary>
            private static void IOCMethod4()
            {
                IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
                IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>();
                bll.ShowResult();
            }
    复制代码

    运行程序,发现每次只会出现 AnalyseB 类的结果。即 IAnalyse=最后注册的类型 。Unity 的 RegisterType 方法有个参数string name。用key来区分子类型。修改代码

    复制代码
    //core 层
    public static IUnityContainer DependencyRegisterContainer()
            {
                IUnityContainer container = new UnityContainer();
                container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
                         .RegisterType<IDAL.IAnalyse, DAL.Analyse>()
                         .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B");
                return container;
            }
    
    //// UI 层
            private static void IOCMethod4()
            {
                IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
                IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-B");
                bll.ShowResult();
            }
    
    ////同时运行 IOCMethod2() 和 IOCMethod4()
    复制代码

    结果

    这样就是实现了子类多个的 IOC 容器注册。(注意,key一定要区分大小写)

     【带参的构造函数】

    Web程序与数据库交互的时候,需要从前台获取查询条件,我在 AnalyseB 中写了一个带有 string 类型的构造函数。代码如下

    复制代码
     public class AnalyseB:IBLL.IAnalyse
        {
            public string StrWhere { get; set; }
    
            /// <summary>
            /// 查询条件的构造函数
            /// </summary>
            /// <param name="strWhere"></param>
            public AnalyseB(string strWhere)
            {
                this.StrWhere = strWhere;
            }
    
            ////使用依赖注入
            [Dependency]
            public IDAL.IAnalyse dal { get; set; }
    public void ShowResult() { dal.ShowResult2(StrWhere); } }
    //// 修改 core 层 容器注册方法 public static IUnityContainer DependencyRegisterContainer() { IUnityContainer container = new UnityContainer(); container.RegisterType<IBLL.IAnalyse, BLL.Analyse>() .RegisterType<IDAL.IAnalyse, DAL.Analyse>() .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B", (new InjectionConstructor(typeof(string)))); return container; } ////UI 层调用代码如下 private static void IOCMethod4() { IUnityContainer container = DependencyRegister.DependencyRegisterContainer(); IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-B", new ParameterOverride("strWhere", " WHERE 1=1 ")); bll.ShowResult(); }
    复制代码

     AnalyseB 构造函数带有string 类型的参数,在 容器注册的时候,需要注册 参数的类型  new InjectionConstructor(typeof(string),typeof(param2),...) (这里也可以是常量)。调用时用ParameterOverride(构造函数参数名,参数值) 来重新给参数赋值。

    如果参数是其它类型又怎么办。例如数据以表格形式呈现时,需要分页。我在BLL 层加了一个分页接口。修改代码

    复制代码
    ////新增分页接口
    public interface IPager
        {
            string GetPager();
        }
    
    public class AnalysePager : IBLL.IPager
        {
            public string GetPager()
            {
                return "数据已分页";
            }
        }
    
    public class AnalyseB:IBLL.IAnalyse
        {
            public string StrWhere { get; set; }
            public IBLL.IPager Pager { get; set; }
    
            public AnalyseB(IBLL.IPager pager, string strWhere)
            {
                this.Pager = pager;
                this.StrWhere = strWhere  + pager.GetPager();
            }
    
            ////使用依赖注入
            [Dependency]
            public IDAL.IAnalyse dal { get; set; }
    
            
            public void ShowResult()
            {
                dal.ShowResult2(StrWhere);
            }
        }
    
    ////修改core层 方法
     public class DependencyRegister
        {
            public static IUnityContainer DependencyRegisterContainer()
            {
                IUnityContainer container = new UnityContainer(); 
                container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
                         .RegisterType<IDAL.IAnalyse, DAL.Analyse>()
                         .RegisterType<IBLL.IPager,BLL.AnalysePager>()
                         .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-B", (new InjectionConstructor(typeof(IBLL.IPager) , typeof(string))));
                return container;
            }
        }
    
    ////UI 层代码不变
    复制代码

    运行结果:

    【属性注入】

    修改一下构造函数,把参数 IPager 提成属性。 代码如下

    复制代码
    public class AnalyseB:IBLL.IAnalyse
        {
            public string StrWhere { get; set; }
    
            public IBLL.IPager Pager { get; set; }
    
            /// <summary>
            /// 查询条件的构造函数
            /// </summary>
            /// <param name="strWhere"></param>
            public AnalyseB(IBLL.IPager pager, string strWhere)
            {
                this.Pager = pager;
                this.StrWhere = strWhere  + pager.GetPager();
            }
            public AnalyseB(string strWhere)
            {
                this.StrWhere = strWhere;
            }
    
            ////使用依赖注入
            //[Dependency]
            public IDAL.IAnalyse dal { get; set; }
    
            
            public void ShowResult()
            {
                StrWhere += Pager.GetPager();
                dal.ShowResult2(StrWhere);
            }
    
    //// core 
     public static IUnityContainer DependencyRegisterContainer()
            {
                IUnityContainer container = new UnityContainer();
                container.RegisterType<IBLL.IAnalyse, BLL.Analyse>()
                         .RegisterType<IDAL.IAnalyse, DAL.Analyse>()
                         .RegisterType<IBLL.IPager, BLL.AnalysePager>()
                    //.RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-C", (new InjectionConstructor(typeof(IBLL.IPager) , typeof(string))));
                         .RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-D", new InjectionMember[]
                             {
                                 new InjectionConstructor(typeof (string)),
                                 new InjectionProperty("Pager"), 
                                 new InjectionProperty("dal"), 
                             });
                return container;
            }
    复制代码

    自己在实际使用过程总结了几点:

    1.使用属性注入,属性不能再构造函数中使用,否则会报为实例化对象异常。(关于这点自己持怀疑态度,有可能是自己不正确的使用造成的。希望和大家讨论

    2.BLL.AnalyseB 本身有个属性 dal. 如果使用属性注入,则所有属性都须加入 InjectionMember[] .

    3.最好使用构造注入。

    (以上三点是在项目使用过程中,自己总结出来。非权威,非标准,有不对的地方希望大家指出。`(*∩_∩*)′)

    【方法注入】

    除开构造注入,属性注入,还有方法注入。使用与属性注入差不多。方法注入尚没有在实际项目中应用过,下面例子是参考其它两种注入方法写的

    复制代码
    ////修改此类,增加字段_pager 和 方法 SetPager
    public class AnalyseB:IBLL.IAnalyse
        {
            public string StrWhere { get; set; }
    
            public IBLL.IPager Pager { get; set; }
    
            public IBLL.IPager _pager;
    
            public void SetPager(IBLL.IPager pager)
            {
                this._pager = pager;
            }
    
    
    
            /// <summary>
            /// 查询条件的构造函数
            /// </summary>
            /// <param name="strWhere"></param>
            public AnalyseB(IBLL.IPager pager, string strWhere)
            {
               this.Pager = pager;
                this.StrWhere = strWhere + pager.GetPager();
            }
    
            public AnalyseB(string strWhere)
            {
                this.StrWhere = strWhere;
            }
    
            ////使用依赖注入
            [Dependency]
            public IDAL.IAnalyse dal { get; set; }
    
    
            public void ShowResult()
            {
                //StrWhere += Pager.GetPager();
                StrWhere += this._pager.GetPager();
                dal.ShowResult2(StrWhere);
            }
    
    ////增加core层的注入方式
    container..RegisterType<IBLL.IAnalyse, BLL.AnalyseB>("Analyse-E", new InjectionMember[]
                             {
                                 new InjectionConstructor(typeof (string)),
                                 new InjectionMethod("SetPager",container.Resolve<IBLL.IPager>()),
                             });
    
    ////UI 层调用
    /// <summary>
            /// 方法注入
            /// </summary>
            public static void IOCMethod6()
            {
                IUnityContainer container = DependencyRegister.DependencyRegisterContainer();
                IBLL.IAnalyse bll = container.Resolve<IBLL.IAnalyse>("Analyse-E",
                                                                     new ParameterOverride("strWhere", " WHERE 1=1 "));
                bll.ShowResult();
            }
    复制代码

    (个人觉得方法注入很鸡肋,其实就是属性注入)

    以上是我在项目运用过程中总结出来的一些心得,尚有许多不足的地方,先抛砖引玉,与大家共同讨论,共同学习。

     【源码下载】

    作者:IT农民 
    出处:http://ttrjba.cnblogs.com 
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
     
    分类: ASP.NETIOC
  • 相关阅读:
    一分钟了解Docker
    RobotFramework
    RobotFramework不同版本优劣势
    从零学习基于Python的RobotFramework自动化
    Python 接口自动化常用方法封装
    (转载)解决MySql 数据库 提示:1045 access denied for user 'root'@'localhost' using password yes
    (转载)html中div使用自动高度
    javascriptDOM对象之scrollTo()方法,滚动到页面指定位置
    CSS3之响应式布局
    Html5NodeJs安装less之千辛万苦CMD系列
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3518106.html
Copyright © 2011-2022 走看看