业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份

WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多。大家对我做的这个行业的前景有很大的建议啊。虽然市场有困难,但好技术架构肯定是前提。事实也是,当你还是一个孩子准备和一群成年人竞争时,你可以被人轻易的暴力推到,可以被人家多年的经验轻松完虐,别人也会说“大人说话小孩子一边玩去”。这些都是过程,作为一位有准备的小孩会有心理准备的,今天准备把之前的架构中的使用策略实现业务类接口在TCP,HTTP,BLL模式下的实例大家一起交流下。这样说大家可能比较模糊,

我提几个问题。

  1、之前有人问我IBLL是干什么的?    

  例如:

   [ServiceContract]
public interface IRadioListBLL
{
[OperationContract(IsOneWay = false)]
List<RD_RADIO_LIST> Query();
}
 RD_RADIO_LIST

using System;
using Yike.Model.DataBase;
using System.Runtime.Serialization;

namespace Yike.Model.Radio
{
/// <summary>
/// 无线电清单
/// </summary>
[DataContract]
public class RD_RADIO_LIST
{
/// <summary>
///
/// </summary>
[DataMember]
[FieldProperty(PRIMARY_KEY = 1, COLUMN_TYPE = "NUMBER", COLUMN_LENGTH = 22)]
public long REDIO_UKID
{
get;
set;
}
/// <summary>
///
/// </summary>
[DataMember]
[FieldProperty(PRIMARY_KEY = 0, COLUMN_TYPE = "VARCHAR2", COLUMN_LENGTH = 20)]
public string REDIO_NAME
{
get;
set;
}
/// <summary>
///
/// </summary>
[DataMember]
[FieldProperty(PRIMARY_KEY = 0, COLUMN_TYPE = "VARCHAR2", COLUMN_LENGTH = 100)]
public string URL
{
get;
set;
}
/// <summary>
///
/// </summary>
[DataMember]
[FieldProperty(PRIMARY_KEY = 0, COLUMN_TYPE = "VARCHAR2", COLUMN_LENGTH = 100)]
public string DESCRIPTION
{
get;
set;
}
/// <summary>
///
/// </summary>
[DataMember]
[FieldProperty(PRIMARY_KEY = 0, COLUMN_TYPE = "NUMBER", COLUMN_LENGTH = 22)]
public long PRIORITY
{
get;
set;
}
}
}

RD_RADIO_LIST

  首先如@心态要好说的IBLL是业务逻辑层接口,而且还实现wcf的服务契约描述。当然了这个接口和实体是使用Easycord生成的。

  2、上篇中wcf在架构中起的什么作用?

    我们的UI层可能是window、wince。开发语言可能是c#也可能是java。这样我们业务层实现多套肯定不是最好的。很多人在UI层一个操作时会进行数据校验,我通常喜欢将这些校验放在业务层进行。这样我通过wcf提供标准的服务、大家都可以来直接调用不用担心调用前辈的服务自己有什么验证忘记判断,使用wcf客户端不用直接连接数据库,这样安全性、部署的难度都可以有很大改善。

  通过上面的解说,大家应该知道,访问wcf可以用性能比较好的TCP协议,也可以使用可以不用担心防火墙等的Http协议,当然有的时候我们确实需要直接连接数据库。这就是我想说的根据IBLL实现TCP,HTTP,BLL模式访问业务层。

  不啰嗦啦,直接上图:

  

  设计模式的思想可以肯定的说每个程序员都在用,而且肯定不止一种。只不过有的人是通过gof的相关书籍,有的人是通过同事的经验传授...。总结为每一个设计模式方便大家交流和学习。很多设计模式的名字都忘记了,最近又温故了下gof设计模式,有兴趣的小伙伴们可以来161153385设计模式群一起交流。

  在上图中可以看出来至少使用了工厂模式、策略模式、还有模版模式。

    工厂模式:InterfaceHelper的Factory方法是你给我一个接口我给你实例,不管你怎么实现。

    策略模式:这么说就是见招拆招。你要什么我给你什么模式下的实例。      

           switch (_InstanceSource)
{
case "BLL": iGetInstance = new BLLGetInstance(); break;
case "WsHttp": iGetInstance = new WSHttpGetInstance(); break;
case "WsTcp": iGetInstance = new WSTcpGetInstance(); break;
}

    模版模式:InterfaceHelper在Init中需要初始化加载类和服务和接口。在家每个业务层的时候基本都是一样的,需要加载BLL,IBLL,服务的文件,循环类,保存在字典中。

LoadType(string bllFile, string iBllFile, string serverFile)中就是一个模版。

Init()会通过这个模版初始化字典表中。

     private static void Init()
{
string docPath = path + "\\Assembly.xml";
if (File.Exists(docPath))
{
XDocument xdoc = XDocument.Load(docPath);
foreach (XElement element in xdoc.Element("AssemblyInfos").Elements())
{
LoadType(element.Attribute("BLLFileName").Value, element.Attribute("IBLLFileName").Value, element.Attribute("ServeFileName").Value);
}
}
}
 附源码一份

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.ServiceModel;
using System.Xml.Linq;

namespace Yike.Tool.Instance
{
public class InterfaceHelper
{
private static string _InstanceSource = string.Empty;
private static List<BllTypeRelation> dict = new List<BllTypeRelation>();

private static string path
{
get
{
return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
}

public static T Factory<T>()
{
if (string.IsNullOrEmpty(_InstanceSource))
_InstanceSource = GetInstanceSource();
if (dict == null || dict.Count == 0)
Init();
IGetInstance iGetInstance = null;
switch (_InstanceSource)
{
case "BLL": iGetInstance = new BLLGetInstance(); break;
case "WsHttp": iGetInstance = new WSHttpGetInstance(); break;
case "WsTcp": iGetInstance = new WSTcpGetInstance(); break;
}
if (iGetInstance == null)
return default(T);
BllTypeRelation t = dict.Find(d => d.IBll == typeof(T));
if (t != null)
return iGetInstance.GetInstance<T>(t);
else
throw new Exception(path + "不存在");
}

private static string GetInstanceSource()
{
string InstanceSource = string.Empty;
if (ConfigurationManager.AppSettings["InstanceSource"] == null)
InstanceSource = "BLL";
else
InstanceSource = ConfigurationManager.AppSettings["InstanceSource"];
return InstanceSource;
}

private static void Init()
{
string docPath = path + "\\Assembly.xml";
if (File.Exists(docPath))
{
XDocument xdoc = XDocument.Load(docPath);
foreach (XElement element in xdoc.Element("AssemblyInfos").Elements())
{
LoadType(element.Attribute("BLLFileName").Value, element.Attribute("IBLLFileName").Value, element.Attribute("ServeFileName").Value);
}
}
}

private static void LoadType(string bllFile, string iBllFile, string serverFile)
{
if (!File.Exists(path + "\\" + bllFile + ".dll") || !File.Exists(path + "\\" + iBllFile + ".dll"))
return;

Assembly bllAssembly = Assembly.LoadFile(path + "\\" + bllFile + ".dll");
Assembly iBllAssembly = Assembly.LoadFile(path + "\\" + iBllFile + ".dll");
Assembly serverAssembly = null;
if (File.Exists(path + "\\" + serverFile + ".dll"))
serverAssembly = Assembly.LoadFile(path + "\\" + serverFile + ".dll");

Type[] types = bllAssembly.GetTypes();

foreach (Type type in types)
{
string name = type.Name.Replace("BLL", "");
Type t1 = iBllAssembly.GetType(iBllFile + ".I" + type.Name);
Type t2 = null;
if (serverAssembly != null)
t2 = serverAssembly.GetType(serverFile + "." + name + "Server");
if (t1 == null)
continue;
dict.Add(new BllTypeRelation(type, t1, t2));
}

}
}

public class BllTypeRelation
{
public BllTypeRelation(Type bll, Type ibll, Type server)
{
this.Bll = bll;
this.IBll = ibll;
this.Server = server;
}

public Type Bll
{
get;
set;
}

public Type IBll
{
get;
set;
}

public Type Server
{
get;
set;
}
}

public interface IGetInstance
{
T GetInstance<T>(BllTypeRelation t);
}

public class BLLGetInstance : IGetInstance
{
public T GetInstance<T>(BllTypeRelation t)
{
return (T)Activator.CreateInstance(t.Bll);
}
}

public class WSHttpGetInstance : IGetInstance
{
public T GetInstance<T>(BllTypeRelation t)
{
string url = "http://" + ConfigurationManager.AppSettings["ServerIp"] + ":" + ConfigurationManager.AppSettings["ServerPort"] + "/" + t.Server.Name + ".svc";
EndpointAddress ea = new EndpointAddress(url);
return ChannelFactory<T>.CreateChannel(new WSHttpBinding(SecurityMode.None), ea);
}
}

public class WSTcpGetInstance : IGetInstance
{
public T GetInstance<T>(BllTypeRelation t)
{
string url = "net.tcp://" + ConfigurationManager.AppSettings["ServerIp"] + ":" + ConfigurationManager.AppSettings["ServerPort"] + "/" + t.Server.Name + ".svc";

EndpointAddress ea = new EndpointAddress(url);

return ChannelFactory<T>.CreateChannel(new NetTcpBinding(SecurityMode.None), ea);
}
}
}

附源码一份

 
 

业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份的更多相关文章

  1. 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)

    最近看老罗的视频,跟着完成了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口 ...

  2. 基于Python接口自动化测试框架+数据与代码分离(进阶篇)附源码

    引言 在上一篇<基于Python接口自动化测试框架(初级篇)附源码>讲过了接口自动化测试框架的搭建,最核心的模块功能就是测试数据库初始化,再来看看之前的框架结构: 可以看出testcase ...

  3. C#/ASP.NET MVC微信公众号接口开发之从零开发(四) 微信自定义菜单(附源码)

    C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发( ...

  4. C#/ASP.NET MVC微信公众号接口开发之从零开发(三)回复消息 (附源码)

    C#/ASP.NET MVC微信接口开发文章目录: 1.C#/ASP.NET MVC微信公众号接口开发之从零开发(一) 接入微信公众平台 2.C#/ASP.NET MVC微信公众号接口开发之从零开发( ...

  5. Asp.net MVC - 使用PRG模式(附源码)

    阅读目录: 一. 传统的Asp.net页面问题 二.Asp.net MVC中也存在同样的问题 三.使用PRG模式 四.PRG模式在MVC上的实现 一. 传统的Asp.net页面问题 一个传统的Asp. ...

  6. Eclipse开发环境debug模式调试断点从jar跳到源码

    Eclipse开发环境debug模式调试断点从jar跳到源码 说明:本案例使用jsch-0.1.54.jar和源码做test,项目分成两个,一个是jsch的源码,另一个是测试案例 一.下载JSch.的 ...

  7. 3.NetDh框架之缓存操作类和二次开发模式简单设计(附源码和示例代码)

    前言 NetDh框架适用于C/S.B/S的服务端框架,可用于项目开发和学习.目前包含以下四个模块 1.数据库操作层封装Dapper,支持多种数据库类型.多库实例,简单强大: 此部分具体说明可参考博客: ...

  8. 使用工厂方法模式实现多数据库WinForm手机号码查询器(附源码)

    先讲一下简单工厂模式.工厂方法模式.抽象工厂模式的东西: 简单工厂模式(Simple Factory Pattern):工厂类中包含了必要的逻辑判断,根据客户端的选择条件动态实例化相关类,也就是说产品 ...

  9. 2.NetDh框架之简单高效的日志操作类(附源码和示例代码)

    前言 NetDh框架适用于C/S.B/S的服务端框架,可用于项目开发和学习.目前包含以下四个模块 1.数据库操作层封装Dapper,支持多种数据库类型.多库实例,简单强大: 此部分具体说明可参考博客: ...

随机推荐

  1. ArcGIS API for Silverlight 使用GP服务实现要素裁剪功能

    原文:ArcGIS API for Silverlight 使用GP服务实现要素裁剪功能 昨天一QQ好友问了一个关于裁剪的问题,感觉自己也没有帮上什么忙,之后自己做了一个裁剪的例子,不过在做这个例子的 ...

  2. BIZTALK项目中WEB引用WEBSERVICES服务时候报错

    近期工作中须要完毕通过BIZTALK完毕调用WEBLOGIC公布的WebServices服务,环境搭建好后,打开VS开发工具新建一个BIZTALK项目,加入WEB引用将对方公布的地址拷贝上去,能够正常 ...

  3. MySQL 升级方法指南大全

    原文:MySQL 升级方法指南大全 通常,从一个发布版本升级到另一个版本时,我们建议按照顺序来升级版本.例如,想要升级 MySQL 3.23 时,先升级到 MySQL 4.0,而不是直接升级到 MyS ...

  4. 候选键(unique)

    foreign key references  除了关联外键,还可以关联 候选键(unique) 需求 table1 中的  status  int  类型 ,表示状态 ,0 未启动 ,1 已启动,2 ...

  5. iOS程序发布时出现your application is being uploaded解决办法

    当用Xcode发布app时候出现“your application is being uploaded”或者用Application Loader 一直出现“ 正在通过ITUNES STORE进行鉴定 ...

  6. hdu 4869 Task(馋)

    题目链接:hdu 4869 Task 题目大意:有n台机器,m个任务.每一个机器和任务都有有xi和yi.要求机器的xi.yi均大于等于任务的xi和yi才干运行任务. 每台机器一天仅仅能运行一个任务.要 ...

  7. 日积月累系列之分页控件(js源码)

    最近开发了一款分页控件,分享给大家. 主要功能和界面介绍 cform分页控件支持服务端分页.客户端分页.数据过滤.数据排序等功能. 源码介绍 cform-pager分页控件主要由三部分组成:css.s ...

  8. 你要知道的C与C++的区别

    原文:你要知道的C与C++的区别 如果要说C和C++的区别的话,可能可以列出很多方面出来,但是有许多方面的区别是我们学完这两门语言之后就可以 很好的理解和区分的,比如C是面向过程的一门编程语言,C++ ...

  9. html5 Canvas画图3:1px线条模糊问题

    点击查看原文地址: html5 Canvas画图3:1px线条模糊问题 本文属于<html5 Canvas画图系列教程> 接上一篇canvas画线条教程 上次我们讲到,canvas有时候会 ...

  10. easyui datagrid显示进度条控制操作

    在当我们需要控制时间前台实际项目页面datagrid显示进度条的数据加载时运行,和datagrid默认情况下只在有url加载运行时的数据显示方式的进度条.下面的代码手动控制: 打开一个进度条: $(' ...