高分请教架构问题,请指导
大家好!
先说下背景,
毕业后一直是在做B/S方面的中小型企业信息管理系统,一般就是一台AP服务器一台数据库服务器,客户端直接通过浏览器向服务器发送请求,服务器返回HTML页面,这样我的分层架构,MODEL(实体层),IBussiness(业务逻辑处理接口),Bussiness(业务逻辑层),以及网站项目,都在同一台服务器上。
现在要做一个C/S结构的企业应用,这样我就犯难了,没有做过C/S模式下的架构,以下是我的想法:
第一种:可以将MODEL,IDAL,DAL及UI都放在客户端,这样相当于UI直接去操作数据库;
第二种:MODEL,IBussiness,UI为客户端,Bussiness,IBussiness,MODEL为服务端,客户端通过WEBSERVICE和服务端交互,服务端再去操作数据库;
第三种:……
如果使用第一种数据处理逻辑就暴露在客户端了,而且没有一个服务器的中转,估计日后更新程序是一个麻烦事!
我想采用第二种模式,现在想问的是:“我一个业务逻辑处理就是一个类,比如部门表,对应就会有一个部门业务逻辑处理接口,部门业务逻辑处理类,包含部门查询,部门新增等业务处理,这样我就有很多个业务处理逻辑接口,如果一一对应WEBSERVICE,那么WEBSERVICE数量也相当庞大,所以想通过配置和反射来实现通过不同参数调用WEBSERVICE返回对应的IDAL给客户端”,以下是我的代码,估计是序列化问题报错,请大虾们对我上述的思想和以下代码指导下,十分感谢!
服务端WEBSERVICE:
public class WebService1 : System.Web.Services.WebService
{
[WebMethod]
public object InvokeClass()
{
return Assembly.Load("BUSINNESS").CreateInstance("BUSINNESS.Test1");//之后做成配置
}
}
localhost.WebService1 w = new localhost.WebService1();//返回服务端WEBSERVICE对象webservice 企业应用
IDAL.ITest t = (IDAL.ITest)w.InvokeClass();//获取ITest业务逻辑对象 此处报错!
using System.Web.Services;
using System.ComponentModel;
using LY.TEC.Framework.Common.Container;
using LY.TEC.WSCommunication;
namespace LY.TEC.Framework.WebService
{
/// <summary>
/// CurrencyService 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
public class CurrencyService : System.Web.Services.WebService
{
[WebMethod(EnableSession = true)]
public object[] MethodInvoke(object[] objArr)
{
IIOCContainer container = ContainerContext.Container;
IInvokeServerComponent invokeComponent = container.Resolve<IInvokeServerComponent>();
object[] objArrReturn = invokeComponent.InvokeMethod(objArr);
//
return objArrReturn;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using LY.TEC.Core.Configuration;
using LY.TEC.Framework.Common.Container;
using LY.TEC.MicroKernel;
namespace LY.TEC.WSCommunication
{
public class InvokeServerComponent : IInvokeServerComponent
{
private CompressUtil mCompress = new CompressUtil();
private IKernel mKernel = null;
private static Hashtable mCompMaps = Hashtable.Synchronized(new Hashtable());
public InvokeServerComponent(IKernel kernal)
{
mKernel = kernal;
}
public object[] InvokeMethod(object[] args)
{
// 1.解压调用参数
object[] objArrParams = (object[])mCompress.DecryptDecompressObject((byte[])args[0], (byte[])args[1]);
//
string strInterfacename = objArrParams[0] as string;
string strMethodname = objArrParams[1] as string;
object[] objMethodArgs = objArrParams[2] as object[];
// 2. 从容器获取对象
object[] objArrReturn = CallFromIoc(strInterfacename, strMethodname, objMethodArgs);
// 3. 压缩加密
byte[] returnData = null;
byte[] byteCryptanalyze = null;
mCompress.CompressEncryptObject(objArrReturn, ref returnData, ref byteCryptanalyze);
// 压缩后的数据封装为对象数组
object[] objArrCompressedReturn = new object[] { returnData, byteCryptanalyze };
//
return objArrCompressedReturn;
}
private object [] CallFromIoc(string interfaceName,string methodName,object[]args)
{
object[] result = null;
object target = GetObjectFromIOC(interfaceName);
if (target == null)
{
throw new Exception(string.Format("接口{0} 的实现在服务端没有配置",interfaceName));
}
//
MethodInfo[] methods = target.GetType().GetMethods();
MethodInfo targetMethod = null;
foreach (MethodInfo methodInfo in methods)
{
if (methodInfo.Name.Equals(methodName) && (methodInfo.GetParameters().Length == args.Length))
{
ParameterInfo[] pi = methodInfo.GetParameters();
bool b = true;
for (int i = 0; i < pi.Length; i++)
{
if (pi[i].ParameterType.Name != "Nullable`1")
{
if (args[i] == null)
continue;
string sArgName = args[i].GetType().Name;
if (sArgName == "Dictionary`2"
[解决办法]
sArgName == "List`2"
[解决办法]
sArgName == "List`1")
{
sArgName = "I" + sArgName;
}
if (pi[i].ParameterType.Name == "DataTable")
{
if (sArgName.LastIndexOf("DataTable") != -1)
{
if (sArgName.LastIndexOf("DataTable") + 9 == sArgName.Length)
{
sArgName = "DataTable";
}
}
}
if (!(pi[i].ParameterType.Name == sArgName
[解决办法]
pi[i].ParameterType.Name == sArgName + "&"))
{
b = false;
break;
}
}
}
if (b)
{
targetMethod = methodInfo;
break;
}
}
}
//Type[] typeArr = new Type[args.Length];
//for (int i = 0; i < typeArr.Length; i++)
//{
// if (args[i] == null)
// typeArr[i] = null;
// else
// typeArr[i] = args[i].GetType();
//}
//MethodInfo targetMethod = target.GetType().GetMethod(methodName, typeArr);
object objcallResult = null;
if (targetMethod != null)
{
objcallResult = targetMethod.Invoke(target, args);
}
else
{
throw new Exception(string.Format("接口{1}中不存在服务方法{0}",methodName,interfaceName));
}
result = new object[] { objcallResult };
return result;
}
private void LoadMaps()
{
IConfiguration[] compConfigs = mKernel.ConfigurationStore.GetComponents();
foreach (IConfiguration config in compConfigs)
{
if (config.Attributes["webserver"] == "true")
{
string interfacename = config.Attributes["service"].Split(',')[0].Trim();
string id = config.Attributes["id"].Trim();
mCompMaps.Add(interfacename,id);
}
}
}
//TODO: 此处 mCompMaps 存放的是 interfacename / id, 但解析时直接解析的是接口类型,没有判断ID的可用性,是否会出现逻辑错误?
private object GetObjectFromIOC(string interfacename)
{
object result = null;
if (mCompMaps.Count < 1)
{
LoadMaps();
}
IIOCContainer container = ContainerContext.Container;
result = container.Resolve(mCompMaps[interfacename].ToString());
return result;
}
}
}