业务类接口在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 + Visifire绘制地图统计图

    原文:使用ArcGIS API for Silverlight + Visifire绘制地图统计图 最近把很久之前做的统计图又拿出来重新做了一遍,感觉很多时候不复习,不记录就真的忘了,时间是最好的稀释 ...

  2. BZOJ 3689 异或 Trie木+堆

    标题效果:特定n的数量,这种需求n数22 XOR的值前者k少 首先,我们建立了一个二进制的所有数字Trie木,您可以使用Trie木size域检查出一些其他的数字XOR值首先k少 然后,我们要保持一个堆 ...

  3. 【高德地图API】如何获得行政区域?如何制作行政规划图?

    原文:[高德地图API]如何获得行政区域?如何制作行政规划图? 什么是行政规划图?如何获得每个行政区域的边界轮廓图?举例:重庆市 江北区.如图: 官方类参考:http://developer.amap ...

  4. jQuery插件编写及链式编程模型

    jQuery插件编写及链式编程模型小结 JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我 ...

  5. [CLR via C#]7. 常量和字段

    原文:[CLR via C#]7. 常量和字段 7.1 常量 常量(constant)是一个特殊的值,它是一个从不变化的值. 在定义常量时,它的值必须在编译时确定.确定之后,编译器将常量的值保存到程序 ...

  6. 蜗牛—Hibernate之初识配置

    下载Hibernate的jar包 把下面jar文件考到项目lib下 然后在myeclipse中打开database的view视图创建一个新的数据库连接 接下来,配置连接,须要导入ORACLE的jar包 ...

  7. easyui dataBox 增加一天,减少一天

    <table> <tr> <td><a href="javascript:void(0)" class="easyui-link ...

  8. DataTable与实体类的转换

    多年前写的DataTable与实体类的转换,已放github 阅读目录 介绍 起因 代码 UnitTest GitHub 介绍 很多年前一直使用Ado.net,后来慢慢转型到其他的orm,在转型过程中 ...

  9. 原生AJAX基础讲解及兼容处理

    原文:原生AJAX基础讲解及兼容处理 AJAX = Asynchronous JavaScript and XML (异步的JavaScript和XML). AJAX不是新技术 ,但却是热门的技术.它 ...

  10. Net Framework中的提供的常用委托类型

    .Net Framework中的提供的常用委托类型   .Net Framework中提供有一些常用的预定义委托:Action.Func.Predicate.用到委托的时候建议尽量使用这些委托类型,而 ...