注意:在底部澄清了我的问题。
我想知道是否有一种(合理的)模式来处理来自老的主机系统的请求/响应? 在下面的示例中,IQ是请求,RSIQ是响应。 在第一个示例中,我正在请求所有帐户代码的列表,在第二个请求中,我要求每个帐户代码的关闭日期。 由于这些仅通过序数位置链接,因此很容易将数据提取到结构化数据类中。 在这种情况下,每个响应代表多条记录。
在第2个示例中,我正在请求单个记录的几个信息。 在这种情况下,每个响应代表单个记录和一些数据点。
这是客户端向服务器发送的消息,以请求从数据库中获取特定信息。
The inquiry message has this general format:
IQ~<msg id>~A<unit#>~B<device type>~D<acct#>~F<password>~G<file>~H<hierarchicrecordpath>~J<field>
**One field from many records**:
Beginning with first share (ordinal zero) on Account 101 return all the Share ID fields in first
message then get all Close Dates in second message. IDs and Close Dates correspond
positionally within the two responses.
IQ~1~A0~BVENDOR~D101~F7777~HSHARE=0~JID=ALL
RSIQ~1~K0~JID=0000~JID=0003~JID=0004~JID=0005~JID=0025~JID=0050
IQ~1~A0~BVENDOR~D101~F7777~HSHARE=0~JCLOSEDATE=ALL
RSIQ~1~K0~JCLOSEDATE=00000000~JCLOSEDATE=20030601~JCLOSEDATE=00000000~JCLOSEDATE=00000000~JCLOSEDATE=00000000~JCLOSEDATE=00000000
**Many fields from one record**:
Using the previous requests get additional information from open shares (two examples).
IQ~1~A0~BVENDOR~D101~F7777~HSHARE#0005~JCLOSEDATE~JSHARECODE~JDIVTYPE~JBALANCE~JAVAILABLEBALANCE
RSIQ~1~K0~JCLOSEDATE=00000000~JSHARECODE=0~JDIVTYPE=2~JBALANCE=234567~JAVAILABLEBALANCE=234567
IQ~1~A0~BVENDOR~D101~F7777~HSHARE#0025~JCLOSEDATE~JSHARECODE~JDIVTYPE~JBALANCE~JAVAILABLEBALANCE
RSIQ~1~K0~JCLOSEDATE=00000000~JSHARECODE=1~JDIVTYPE=5~JBALANCE=654321~JAVAILABLEBALANCE=654321
背景:我已经在我的应用程序中使用了工作单元/存储库模式。每个应用程序都处理多个数据存储区(SQL数据库、文件、Web服务、套接字等)。其思想是每个存储库公开一个(完整)数据模型的一部分。
我最初的想法是在存储库中创建我需要的特定调用,例如
GetAccounts(acctId)
,并使方法发送正确的请求,然后从所有响应中构建对象图,最终返回对象图。现在我正在寻找一种设计模式来处理这些方法的内部,而不必执行大量的string.Replace()语句或StringBuilder调用。由于任何请求的最大大小为8000个字符,您可以看到~J字段可能会变得非常复杂。(而且我仍在寻找所有可能进入~J字段的代码。)
以下是一个小例子:
public List<SymitarAccount> GetAccounts(string accountId)
{
var retAccounts = new List<SymitarAccount>();
// Is there a pattern to do this repetitve but ever changing task? //
// Example: Mock response then handle... //
// NOTE: There will be many request/response calls here, not just one! //
var rsp = @"RSIQ~1~K0~JCLOSEDATE=00000000~JSHARECODE=1~JDIVTYPE=5~JBALANCE=654321~JAVAILABLEBALANCE=654321";
var response = rsp.Split(new[] {'~'});
foreach (var q in response)
{
if (q.StartsWith("J") && q.Contains("="))
{
// get Key Value Pair //
// map KVP to SymitarAccount data point (big ugly switch(){}??) //
sa.Id = // KVP for ID //
sa.Balanace = // KVP for BALANCE //
}
retAccounts.Add(sa);
}
return retAccounts;
}
有什么想法或者想法吗?
注意:我正在使用C#(最新版本)。
附加说明1:
public List<SymitarAccount> GetAccounts(string accountId)
{
var retAccounts = new List<SymitarAccount>();
// Get all account IDs...
var response = UnitOfWork.SendMessage("IQ~1~A0~BVENDOR~D101~F7777~HSHARE=0~JID=ALL");
ParseResponse(response, ref retAccounts);
// Get all account close dates (00000000 means it is open)...
response = UnitOfWork.SendMessage("IQ~1~A0~BVENDOR~D101~F7777~HSHARE=0~JCLOSEDATE=ALL");
ParseResponse(response, ref retAccounts);
// Get extra info for all OPEN accounts...
foreach (var account in retAccounts.Where(a => !a.IsClosed))
{
var request = "IQ~1~A0~BVENDOR~D101~F7777~HSHARE#[acct]~JCLOSEDATE~JSHARECODE~JDIVTYPE~JBALANCE~JAVAILABLEBALANCE";
request = request.Replace("[acct]", account.Id.ToString("0000"));
response = UnitOfWork.SendMessage(request);
ParseResponse(response, ref retAccounts, account.Id);
}
return retAccounts;
}
private void ParseResponse(string response, ref List<SymitarAccount> accountList, int? id = null)
{
var list = response.Split(new[] {'~'});
var index = 0;
var chain = new ChainInquiryAccountInfo();
var parser = chain.Parser;
foreach (var q in list.Where(q => q.StartsWith("J"))) // && q.Contains("=")))
{
if (accountList.Count < index || accountList[index] == null)
accountList.Add(new SymitarAccount {PositionalIndex = index});
var val = q.Split(new[] {'='});
if ((id.HasValue && accountList[index].Id == id.Value) || !id.HasValue)
accountList[index] = parser.Parse(val, accountList[index]);
index++;
}
}
~JKEY=VALUE
这样,简单的正则表达式匹配就足够了。 - Konrad Kokosa~[A-Z]
,如果你想要能够同时用解析器进行发送和接收。 - Bob.