zoukankan      html  css  js  c++  java
  • 小菜模块化框架设计-复用性登录组件

    背景

      到TL有整整一年了,在这一年中公司从无到有,完成了两个自动化系统整合项目,老板一直强调模块化设计这个理念,可是由于团队基础实在是薄弱,很多规范没办法执行起来,以致于这两个项目的源码惨不忍睹,代码写得很乱,可以重复利用的模块实在是太少。所以今年我主要的精力投在软件开发规范化这一块,以系统可扩展,模块化,可复用性为原则。

      虽然自已技术还是个小菜,但只要有思想就应该是简单的问题,那么我从一个“用户登录模块”设计开始,把这个模块抽离出来,让所有子系统都能够复用这个登录组件,并且降低模块与主框架之间耦合。

      在制造业的系统架构中,一般分为好几个工作站,每个工作站都有一个子系统,每个子系统都有需要有用户登录权限控制,所以这就意味着每个子系统都要开发这个模块,如果子系统比较多,这样开发成本就比较高,重复代码也很多,我分析了一下,这个用户登录模块有如下特点:

        • 有统一的界面风格
        • 模块根据用户权限不同加载对应的系统子系统
        • 模块标题不一样

      我们如何设计达到组件可以重复利用?

      1. 复用性:让所有子系统都能够重复利用这个用户登录
      2. 易用性:通过配置文件根据不同的子系统设置不一样的系统标题,子系统主框架调用组件简单化
      3. 我后台做一个WCF服务作为用户权限逻辑处理,登录组件直接调这个服务,把用户登录逻辑处理层从系统框架主分离出来成一个独立模块,子模块只需要引入这个组 件,做相应的配置,调用用户验证接口,当登录成功时,组件内部会消息通知主框架(订阅消息)进行启动加载主界面,从而达到成功登录的目的。

      设计思想

      image

      设计步骤

      1.设计WCF Service作后台用户登录验证处理

      using System.ServiceModel;
      using Xiaocai.Security.IDAL;
      
      namespace Xiaocai.Commons
      {
          // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IUserService" in both code and config file together.
          [ServiceContract]
          public interface ILoginService
          {
              [OperationContract]
              AuthUser CheckUser(string userId, string password);
          }
      }
      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Runtime.Serialization;
      using System.ServiceModel;
      using System.Text;
      using Xiaocai.Commons;
      using Xiaocai.Security.Core.Admin;
      using Xiaocai.Security.Core.Helpers;
      using Xiaocai.Security.IDAL;
      
      namespace Xiaocai.SystemHelper.Services
      {
          // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "UserService" in code, svc and config file together.
          public class LoginService : ILoginService
          {
              private AuthController _controller;
              public LoginService()
              {
                  _controller=new AuthController();
              }
              public AuthUser CheckUser(string userId, string password)
              {
                  AuthUser authUser=null;
                  bool result=_controller.Login(userId, password);
                  if (result)
                  {
                      authUser = _controller.AuthUser;
                  }
                  return authUser;
              }
          }
      }

      我主要总结原理,很多细节就不多写了,所以服务中的验证我封装在另一组件中,此处省略。

      2.发布这个WCF服务到IIS服务器中,测试如一下是否发布成功,出现如下页面表示已成功:

      image

       

      3.调用服务客户端

      using System;
      using System.ServiceModel;
      using Xiaocai.Commons;
      using Xiaocai.Security.IDAL;
      
      namespace Xiaocai.SystemHelper.Proxy
      {
          public class LoginHelper
          {
              public static AuthUser OnLogin(string userId,string password)
              {
                  AuthUser authUser = null;
                  using (ChannelFactory<ILoginService> channelFactory = new ChannelFactory<ILoginService>("userService"))
                  {
                      ILoginService proxy = channelFactory.CreateChannel();
                      using (proxy as IDisposable)
                      {
                          authUser = proxy.CheckUser(userId, password);
                          return authUser;
                      }
                  }
              }
          }
      }

       

      4.新建一Winform项目作为登录组件,命名为Xiaocai.SecurityControlLibaray,把项目输出类型改为类库,以便子系统主框引入调用。

      /******************************************************************************
      * This document is the property of ShangHai TLian Agent Technology Co., Ltd. (TLAgent).
      * No exploitation or transfer of any information contained herein is permitted 
      * in the absence of an agreement with Xiaocai
      * and neither the document nor any such information
      * may be released without the written consent of Xiaocai
      *  
      * All right reserved by Xiaocai  
      *******************************************************************************
      * Owner: Agan
      * Version: 1.0.0.0
      * Component:for login function
      * Function Description:*
      * Revision / History
      *------------------------------------------------------------------------------
      * Flag     Date     Who             Changes Description
      * -------- -------- --------------- -------------------------------------------
      *   1       20130715 Agan           File created
      
      *------------------------------------------------------------------------------
      */
      
      using System;
      using System.Configuration;
      using System.Windows.Forms;
      using Xiaocai.Commons;
      using Xiaocai.Security.IDAL;
      using Xiaocai.SystemHelper.Proxy;
      namespace Xiaocai.SecurityControlLibaray
      {
          public partial class LoginForm : Form
          {
              public LoginForm()
              {
                  InitializeComponent();
              }
      
              public virtual string Title { get; set; }
      
              private void LoginForm_Load(object sender, EventArgs e)
              {
                  if (string.IsNullOrEmpty(ConfigurationManager.AppSettings["Title"]))
                  {
                      prgTitle.Text = string.Format("{0}", Title);
                  }
                  else
                  {
                      prgTitle.Text = string.Format("{0}", ConfigurationManager.AppSettings["Title"]);
                  }
               
                  txtUserId.Select();
              }
      
              private void OnLogin(object sender, EventArgs e)
              {
                  string userId = txtUserId.Text.Trim();
                  string password = txtPassWord.Text.Trim();
                  if (string.IsNullOrEmpty(userId) || string.IsNullOrEmpty(password))
                  {
                      if (string.IsNullOrEmpty(userId))
                      {
                          MessageHelper.ShowError("用户名不能为空!");
                          txtUserId.Focus();
                          txtUserId.SelectAll();
                          return;
                      }
                      if (string.IsNullOrEmpty(password))
                      {
                          MessageHelper.ShowError(@"密码不能为空!");
                          txtUserId.Focus();
                          txtUserId.SelectAll();
                          return;
                      }
                     
                      txtUserId.Focus();
                      txtUserId.SelectAll();
                      return;
                  }
      
                  AuthUser authUser = LoginHelper.OnLogin(userId, password);
                  if (authUser!=null)
                  {
                      this.Hide();
                      EventService.Publish(authUser);//用户验证成功,发布消息,把登录用户传送出去
                      Application.ThreadException += Application_ThreadException;
                  }
                  else
                  {
                      MessageHelper.ShowError("用户名或密码不正确,请联系管理员!");
                      txtUserId.Focus();
                      txtUserId.SelectAll();
                  }
              }
      
              private static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs ex)
              {
                  string message = string.Format("{0}
      操作发生错误,您需要退出系统么?", ex.Exception.Message);
                  MessageBox.Show(message);
                  Application.Exit();
              }
      
              private void OnCancel(object sender, EventArgs e)
              {
                  Application.Exit();
              }
      
      
              private void txtPassWord_KeyDown(object sender, KeyEventArgs e)
              {
                  if (e.KeyCode == Keys.Enter)
                  {
                      OnLogin(sender,e);
                  }
              }
      
              private void txtUserId_KeyDown(object sender, KeyEventArgs e)
              {
                  if (e.KeyCode == Keys.Enter)
                  {
                      txtPassWord.Focus();
                  }
              }
          }
      }

       

      6.系统子框架调用

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Windows.Forms;
      using TLAgent.Commons;
      using TLAgent.Security.Core;
      using TLAgent.Security.IDAL;
      using TLAgent.SecurityControlLibaray;
      
      namespace TLAgent.Assembling.SecurityManager
      {
          static class Program
          {
              /// <summary>
              /// The main entry point for the application.
              /// </summary>
              [STAThread]
              static void Main()
              {
                  Application.EnableVisualStyles();
                  Application.SetCompatibleTextRenderingDefault(false);
                  AppCore.Startup();
                  //Application.Run(new LoginForm());
                  OnLonin();
              }
      
              private static void OnLonin()
              {
                  //订阅消息
                  EventAggregatorRepository.EventAggregator
            .GetEvent<ReceiveObjectEvent>()
            .Subscribe(SuccessLogin);
                  Application.Run(new LoginForm());
              }
              /// <summary>
              /// 登录成功加载主窗体
              /// </summary>
              /// <param name="objParam">用户实体对象</param>
              private static void SuccessLogin(object objParam)
              {
                  SecurityControlLibaray.SplashScreen.Splasher.Show(typeof(SplasherForm));
                  MainForm form = new MainForm();
                  var user = objParam as AuthUser;
                  if (user != null)
                  {
                      form.AuthUser = user;
                  }
                  form.StartPosition = FormStartPosition.CenterScreen;
                  form.ShowDialog();
              }
          }
      }

      7.配置文件中设置,如下:

      <?xml version="1.0"?>
      <configuration>
        <!--WCF服务配置文件-->
        <system.serviceModel>
          <client>
            <endpoint address="http://localhost/SystemServices/LoginService.svc" binding="basicHttpBinding" contract="Xiaocai.Commons.ILoginService" name="userService"/>
          </client>
        </system.serviceModel>
        
        <appSettings>
          <add key="Title" value="用户权限管理系统"/><!--系统标题设置-->
          <add key="Copyright" value=" 版权所有:小菜成長記"/><!--系统版权设置-->
            <!-- Database with WebService -->
          <add key="IsRemote" value="N"/>
          <add key="GlobalSessionFactory" value="Xiaocai.Security.DAL.Global.SQLServerSessionFactory,Xiaocai.Security.DAL.Global"/>
      
          <!-- Database without WCFService -->
      
          <add key="Database.SqlServerConn" value="Data Source=localhost,1433;Network Library=DBMSSOCN;Initial Catalog=SecurityDB;User ID=root;Password=12345;"/>
        </appSettings>
      </configuration>

      运行子系统,显示如下:

      image

      这个标题可以根据不同子系统功能在配置文件中作对应设置,到此基本完成这个登录组件的设计,这个组件可以用于所有子系统的登录界面,多次重复利用,减少开发成本。

      附:因本人技术有限,也许会有更好的方法做这个模块化设计,希望高人指点,在不断学习中进步。

    1. 相关阅读:
      What the key facts to choose Row Store and Column Store 沧海
      自定义数据源(ECC>BW) 沧海
      What is SAP HANA appliance software 沧海
      安装BI_CONT时遇到Open Data Extraction Requests的问题 沧海
      Process Chain\DTP\Infopackage相关的几个table和function module 沧海
      Note 741478 FAQ: Materialized views 沧海
      HANA 与 Exalytics 的对比 沧海
      SAP HANA database and how to improve performance 沧海
      SAP HANA 已实施的客户清单 沧海
      BW BEx的VBA开发接口介绍 沧海
    2. 原文地址:https://www.cnblogs.com/aganqin/p/3330135.html
    Copyright © 2011-2022 走看看