SilverLight 기업 응용 프레임워크 디자인[3] 서버 디자인
9982 단어 silverlight
클라이언트가 요청할 때
요청의 유형과 유형에 포함된 방법을 편리하게 알기 위해
우리는 서비스 유형과 방법을 정적 사전에 캐시했다
코드는 다음과 같다.
public class WCFRouteTable
{
static Dictionary<string, Type> routeService;
static Dictionary<string, MethodInfo> routeMethods;
static WCFRouteTable()
{
routeService = new Dictionary<string, Type>();
routeMethods = new Dictionary<string, MethodInfo>();
var ass = (typeof(WCFRouteTable)).Assembly;
var ts = ass.GetTypes();
foreach (var t in ts)
{
if (t.FullName.StartsWith("RTMDemo.Host.WCF"))
{
routeService.Add(t.FullName, t);
foreach (var m in t.GetMethods())
{
var mName = string.Format("{0}.{1}", t.FullName, m.Name);
routeMethods.Add(mName, m);
}
}
}
}
public static Type GetWCFType(string key)
{
Type result = null;
if (routeService.ContainsKey(key))
{
result = routeService[key];
}
return result;
}
public static MethodInfo GetMethodInfo(string key)
{
MethodInfo result = null;
if (routeMethods.ContainsKey(key))
{
result = routeMethods[key];
}
return result;
}
}
2: HTTP 요청 호스팅
웹config에 요청을 위탁 관리할 모듈을 추가합니다
<modules>
<add name="WcfHttpModule" type="RTMDemo.Host.WCFHttpModule, RTMDemo.Host"/>
</modules>
위탁 요청에 대응하는 클래스의 코드는 다음과 같다
public class WCFHttpModule:IHttpModule
{
public void Dispose() { }
/// <summary>
///
/// </summary>
/// <param name="context"></param>
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, args) =>
{
string relativeAddress = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.Remove(0, 2);
Type serviceType = WCFRouteTable.GetWCFType(relativeAddress);
if (null == serviceType)
{
return;
}
IHttpHandler handler = new WCFHandler(serviceType);
context.Context.RemapHandler(handler);
};
}
}
이 줄 코드를 통해
Type serviceType = WCFRouteTable.GetWCFType(relativeAddress);
사용자는 다음 경로를 요청하기만 하면
http://localhost/RTMDemo.Host/RTMDemo.Host.WCF.MenuService
MenuService 유형이 제공됩니다.
그리고 서비스 유형을 지정한 프로세서에 전달합니다
3. 요청 처리
WCFHandler 클래스에서 가장 중요한 것은
요청 처리 방법
코드는 다음과 같다.
/// <summary>
///
/// </summary>
/// <param name="context"></param>
public void ProcessRequest(HttpContext context)
{
try
{
List<object> paramList = new List<object>();
JavaScriptSerializer jss = new JavaScriptSerializer();
var MethodKey = context.Request["MethodKey"];
var minfo = WCFRouteTable.GetMethodInfo(MethodKey);
var si = new MethodInvoker(minfo);
ParameterInfo[] ps = minfo.GetParameters();
var pstrs = context.Request.Form.AllKeys.OrderBy(m=>m).ToArray();
var pIndex = 0;
for(var i=0;i<pstrs.Length;i++)
{
if (string.IsNullOrEmpty(pstrs[i]))
{
continue;
}
if (pstrs[i].StartsWith("p"))
{
var pStr = context.Request[pstrs[i]];
var obj = jss.Deserialize<object>(pStr);
var bts = Encoding.UTF8.GetBytes(pStr);
MemoryStream mss = new MemoryStream(Encoding.UTF8.GetBytes(pStr));
DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(ps[pIndex].ParameterType);
var p = jsonSerializer.ReadObject(mss);
paramList.Add(p);
pIndex += 1;
}
}
//todo:
var instance = Activator.CreateInstance(ServiceType);
var result = si.Execute(instance,paramList.ToArray());
var ss = jss.Serialize(result);
context.Response.ClearContent();
context.Response.ContentEncoding = Encoding.UTF8;
context.Response.ContentType = "application/json; charset=utf-8";
context.Response.Write(ss);
context.Response.Flush();
}
catch
{
context.Response.Write(" ~<br />");
context.Response.Write("@@@@@@~<br />@@@@@@@~");
return;
}
}
}
주의: 우선 이 코드는 매우 큰 최적화 공간이 있다.엄격한 테스트도 거치지 않았다.근데 생각이 기본적으로 이래요.
처리 요청은 주로 다음과 같은 작업을 수행합니다.
1.
일단 요청 POST에 올라온 정보에 따라 실행을 준비하는 방법.
var MethodKey = context.Request["MethodKey"];var minfo = WCFRouteTable.GetMethodInfo(MethodKey);
MethodInvoker는 이따가 얘기할게요.
2.
방법의 매개 변수를 순서대로 추출하고 DataContractJsonSerializer로 반서열화하여 대상으로 합니다
메소드 매개 변수는 JSON 문자열로 전달됩니다.
3.
반사로 서비스의 실례를 만들었습니다
그리고 이 실례적인 방법을 호출한다
메서드의 반환 값을 얻어 JSON 문자열로 시리얼화합니다.
4.
반환 값을 클라이언트에 JSON으로 내보내기
기타
1.
MethodInvoker는 조 씨의 클래스를 사용합니다.구체적으로 어떤 문장인지 나는 이미 찾을 수 없다.
public class MethodInvoker
{
private Func<object, object[], object> m_execute;
public MethodInvoker(MethodInfo methodInfo)
{
this.m_execute = this.GetExecuteDelegate(methodInfo);
}
public object Execute(object instance, params object[] parameters)
{
return this.m_execute(instance, parameters);
}
private Func<object, object[], object> GetExecuteDelegate(MethodInfo methodInfo)
{
ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");
ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
List<Expression> parameterExpressions = new List<Expression>();
ParameterInfo[] paramInfos = methodInfo.GetParameters();
for (int i = 0; i < paramInfos.Length; i++)
{
var ce = Expression.Constant(i);
BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter,ce);
UnaryExpression valueCast = Expression.Convert(valueObj, paramInfos[i].ParameterType);
parameterExpressions.Add(valueCast);
}
var instanceE = Expression.Convert(instanceParameter, methodInfo.ReflectedType);
Expression instanceCast = methodInfo.IsStatic ? null : instanceE;
MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);
if (methodCall.Type == typeof(void))
{
Expression<Action<object, object[]>> lambda = Expression.Lambda<Action<object, object[]>>(methodCall, instanceParameter, parametersParameter);
Action<object, object[]> execute = lambda.Compile();
return (instance, parameters) =>
{
execute(instance, parameters);
return null;
};
}
else
{
UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));
Expression<Func<object, object[], object>> lambda =Expression.Lambda<Func<object, object[], object>>(castMethodCall, instanceParameter, parametersParameter);
return lambda.Compile();
}
}
}
2.
서비스 클래스와 데이터 접근 클래스는 특별한 것이 없습니다
저는 서비스 종류 하나만 공개할게요.
public class MenuService
{
public List<MenuM> GetAllMenu()
{
using (var DA = new MenuDA())
{
var result = DA.GetAllMenu();
return result;
}
}
public void DelMenu(Guid Id)
{
using (var DA = new MenuDA())
{
DA.DelMenu(Id);
}
}
public void AddMenu(MenuM m)
{
using (var DA = new MenuDA())
{
DA.AddMenu(m);
}
}
public void UpdateMenu(MenuM m)
{
using (var DA = new MenuDA())
{
DA.UpdateMenu(m);
}
}
}
Menuda는 데이터 액세스 클래스입니다.
평범해서 코드를 공개하지 않겠습니다.
3.
이 작업을 마치면
저희는 클라이언트에서 폼만 만들면 돼요.
그리고 폼 포스터를 지정한 경로로
서비스 방문을 완료할 수 있습니다!
---------------------------------------------------------------
마음에 드시면 제 글을 추천해주세요.
감사합니다~
나는 정말 너희들의 지지가 필요하다
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Silverlight animation performanceAnimation performance can be improved with several configurations: Desired Frame Rate Configure in the WEB project: Hard...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.