业务类接口在TCP,HTTP,BLL模式下的实例 设计模式混搭 附源码一份
WinForm酒店管理软件--框架这篇随笔可以说是我写的最被大家争议的随笔,一度是支持和反对是一样的多。大家对我做的这个行业的前景有很大的建议啊。虽然市场有困难,但好技术架构肯定是前提。事实也是,当你还是一个孩子准备和一群成年人竞争时,你可以被人轻易的暴力推到,可以被人家多年的经验轻松完虐,别人也会说“大人说话小孩子一边玩去”。这些都是过程,作为一位有准备的小孩会有心理准备的,今天准备把之前的架构中的使用策略实现业务类接口在TCP,HTTP,BLL模式下的实例大家一起交流下。这样说大家可能比较模糊,
我提几个问题。
1、之前有人问我IBLL是干什么的?
例如:
[ServiceContract]
public interface IRadioListBLL
{
[OperationContract(IsOneWay = false)]
List<RD_RADIO_LIST> Query();
}
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);
}
}
}
附源码一份