• 怎样才能容易更换DB


    //怎样才能容易更换DB
    //写一个可以对用户插入和获取的方法
    namespace switchDB
    {
        class User
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }
        class SqlServerUser
        {
            public void Insert(User user)
            { }
            public void GetUser(int id)
            { }
        }
        class Program
        {
            static void Main(string[] args)
            {
                User u = new User();
                SqlServerUser ssu = new SqlServerUser();
                ssu.Insert(u);
                ssu.GetUser(1);
            }
        }
    }
    这里的问题是SqlServerUser被硬编码了,只能使用SqlServer,要是多态的话就好了,使用抽象工厂修改:

    namespace switchDB
    {
        class User
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }
        interface IUser
        {
            void Insert(User user);
            void GetUser(int id);
        }

        class SqlServerUser : IUser
        {
            public void Insert(User user)
            { }
            public void GetUser(int id)
            { }
        }
        class AccessUser : IUser
        {
            public void Insert(User user)
            { }
            public void GetUser(int id)
            { }
        }
        //定义IFactory接口
        interface IFactory
        {
            IUser CreateUser();
        }
        //抽象工厂
        class SqlServerFactory : IFactory
        {
            public IUser CreateUser()
            {
                return new SqlServerUser();
            }
        }
        class AccessFactory : IFactory
        {
            public IUser CreateUser()
            {
                return new AccessUser();
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                User u = new User();
                SqlServerFactory f = new SqlServerFactory();
                IUser it = f.CreateUser();
                it.Insert(u);
                it.GetUser(1);
            }
        }
    }

    这样以后增加表Department,就需要增加IDepartment,并实现SqlServerDepartment,和AccessDepartment,还要修改IFactory增加CreateDepartment接口方法,并且在SqlServerFactory和AccessFactory分别实现。其中增加三个是必须的,但是修改IFactory,SqlServerFactory和AccessFactory是多点多于的,也是不可容忍的。
    使用简单工厂改进:
    namespace switchDB
    {
        class User
        {
            public int ID { get; set; }
            public string Name { get; set; }
        }
        interface IUser
        {
            void Insert(User user);
            void GetUser(int id);
        }

        class SqlServerUser : IUser
        {
            public void Insert(User user)
            { }
            public void GetUser(int id)
            { }
        }
        class AccessUser : IUser
        {
            public void Insert(User user)
            { }
            public void GetUser(int id)
            { }
        }
        class DateAccess
        {
            private static readonly string db = "sqlserver";
            public static IUser CreateUser()
            {
                IUser result = null;
                switch(db)
                {
                    case "sqlserver":
                        result = new SqlServerUser();
                        break;
                    case "access":
                        result = new AccessUser();
                        break;
                }
                return result;
            }
        }
        
        class Program
        {
            static void Main(string[] args)
            {
                User u = new User();
                IUser iu = DateAccess.CreateUser();
                iu.Insert(u);
                iu.GetUser(1);
            }
        }
    }


    使用简单工厂放弃IFactory,SqlServerFactory,AccessFactory这三个类,用DataAccess来改进,将来要是要用Oracle,就在DataAccess中增加一个Case,使用这个分支也是不完美的,要是我们可以根据字符串db的值,去某一个地方去找应该实例化的类,这样我们就可以不使用swith了,这种编程方式叫做  依懒注入,使用net反射就可以了:
    格式:Assembly.Load("程序集名称").CreateInstance("类的全权名");
    只要引入Using System.Reflection;就可以了。
    使用反射和不使用发射比较:
    //常规
    IUser result = new SqlServerUser();
    //反射
    using System.Reflection;

    反射中,可以灵活替换"程序集名称"和"类的全权名",灵活性和可以替换性达到了。
    例如:
        class DateAccess
        {
            private static readonly string AssemblyName = "factory";
            private static readonly string db = "sqlserver";
            public static IUser CreateUser()
            {
                string className = AssemblyName + "." + db + "user";
                return (IUser)Assembly.Load(AssemblyName).CreateInstance(className);
            }
        }

    修改之后我们就和switch说再见了,但是我们每次修改数据库,还是修改了db这个字符串的值,要不修改它就更好了,符合开发-封闭原则
    使用反射+配置文件再作改进:
    利用配置文件来解决更改DataAccess的问题
    添加一个App.Config文件:
    <Configuration>
    <appSettings>
    <add key="db" value="sqlserver">
    </appSettings>
    </Configuration>

    代码:
    using System.Configuration;
    private static readonly string db = ConfigurationManager.AppSettings["db"];
    现在我们应用反射,抽象工厂解决了数据库访问,可维护可扩展问题。
    从这个角度,所有的用简单工厂的地方,都可以考虑修改为反射去除switch来完成。



    下面试调用静态方法的反射运用:

    public class T_SizeType
    {
       public static bool pro_T_SizeType_SelectAll(string p_ConnString)
       {
           return true;
       }
    }
    
    
    class Program
    {
       static void Main(string[] args)
       {
           object[] arg = new object[1]{string.Empty};
           typeof(T_SizeType).InvokeMember("pro_T_SizeType_SelectAll",
              BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, arg);
       }
    }

  • 相关阅读:
    2017年度最具商业价值人工智能公司TOP50 榜单发布
    滑动swipe的妙用
    UE3优化
    UE4 框架
    制作HUD
    Component概念
    手游记事
    C++与UnrealScript脚本交互
    unreal Script(US)一些注意事项
    UDK游戏打包详解
  • 原文地址:https://www.cnblogs.com/lmfeng/p/2931863.html
Copyright © 2020-2023  润新知