我認爲你擔心在這種情況下不成熟的優化。一般的經驗法則是 - 除非性能問題實際可衡量,否則不要優化。
考慮到這一點,這個問題可以在一個相當優雅的莊園中解決。我將使用一點緩存反射,這樣我只需拉動PropertyInfo
及其自定義屬性一次。所以你會看到初始連接的性能開銷很小。在這一點上,這是非常快的。
因爲我調用方法Process(數據)一堆時間,就像每秒100次。
我在一臺Windows 10虛擬機中運行這個程序,它有4個內核和8個RAM。我運行了一個測試,對包含100個值的字符串進行了10,000次迭代(沒有使用縮短的字符串),並且我看到每個字符串的平均解析時間爲516.32 ,刻度爲(每1ms爲10,000個刻度)。考慮到您的要求是1秒內100個字符串,這對於您的吞吐量應該足夠快。在1秒的時間內,我能夠解析出超過20,000的數據。每秒解析數將最終高於20,000 I處理,因爲每次使用整個100個元素的字符串而不是更小的更新字符串。
長時間運行可能會有一些GC壓力,我必須運行測試才能看到。這可以通過引入一對對象池來優化,以減少分配。無論採用何種方法,您都會遇到此問題,僅僅因爲您必須將1個字符串解析爲多個值,所以此解決方案無法解決此問題。
讓我們從我的字符串開始,它包含100個元素。
0:FizBam Foo Bar:1:FizBam Foo Bar:2:FizBam Foo Bar:3:FizBam Foo Bar:4:FizBam Foo Bar:5:FizBam Foo Bar:6:FizBam Foo Bar:7:FizBam Foo Bar:8:FizBam Foo Bar:9:FizBam Foo Bar:10:FizBam Foo Bar:11:FizBam Foo Bar:12:FizBam Foo Bar:13:FizBam Foo Bar:14:FizBam Foo Bar:15:FizBam Foo Bar:16:FizBam Foo Bar:17:FizBam Foo Bar:18:FizBam Foo Bar:19:FizBam Foo Bar:20:FizBam Foo Bar:21:FizBam Foo Bar:22:FizBam Foo Bar:23:FizBam Foo Bar:24:FizBam Foo Bar:25:FizBam Foo Bar:26:FizBam Foo Bar:27:FizBam Foo Bar:28:FizBam Foo Bar:29:FizBam Foo Bar:30:FizBam Foo Bar:31:FizBam Foo Bar:32:FizBam Foo Bar:33:FizBam Foo Bar:34:FizBam Foo Bar:35:FizBam Foo Bar:36:FizBam Foo Bar:37:FizBam Foo Bar:38:FizBam Foo Bar:39:FizBam Foo Bar:40:FizBam Foo Bar:41:FizBam Foo Bar:42:FizBam Foo Bar:43:FizBam Foo Bar:44:FizBam Foo Bar:45:FizBam Foo Bar:46:FizBam Foo Bar:47:FizBam Foo Bar:48:FizBam Foo Bar:49:FizBam Foo Bar:50:FizBam Foo Bar:51:FizBam Foo Bar:52:FizBam Foo Bar:53:FizBam Foo Bar:54:FizBam Foo Bar:55:FizBam Foo Bar:56:FizBam Foo Bar:57:FizBam Foo Bar:58:FizBam Foo Bar:59:FizBam Foo Bar:60:FizBam Foo Bar:61:FizBam Foo Bar:62:FizBam Foo Bar:63:FizBam Foo Bar:64:FizBam Foo Bar:65:FizBam Foo Bar:66:FizBam Foo Bar:67:FizBam Foo Bar:68:FizBam Foo Bar:69:FizBam Foo Bar:70:FizBam Foo Bar:71:FizBam Foo Bar:72:FizBam Foo Bar:73:FizBam Foo Bar:74:FizBam Foo Bar:75:FizBam Foo Bar:76:FizBam Foo Bar:77:FizBam Foo Bar:78:FizBam Foo Bar:79:FizBam Foo Bar:80:FizBam Foo Bar:81:FizBam Foo Bar:82:FizBam Foo Bar:83:FizBam Foo Bar:84:FizBam Foo Bar:85:FizBam Foo Bar:86:FizBam Foo Bar:87:FizBam Foo Bar:88:FizBam Foo Bar:89:FizBam Foo Bar:90:FizBam Foo Bar:91:FizBam Foo Bar:92:FizBam Foo Bar:93:FizBam Foo Bar:94:FizBam Foo Bar:95:FizBam Foo Bar:96:FizBam Foo Bar:97:FizBam Foo Bar:98:FizBam Foo Bar:99:FizBam Foo Bar:100:!
我然後創建Attribute
,我可以使用到一個元素映射到模型屬性。
public class MapAttribute : Attribute
{
public MapAttribute(string fieldKey)
{
this.Field = fieldKey;
}
public string Field { get; private set; }
public PropertyInfo Property { get; set; }
public void SetValue(Question question, string value)
{
this.Property.SetValue(question, value);
}
}
現在,在您的模型上,您可以將屬性映射到傳入字段。當一個字段進來時,你將它傳遞給該屬性以及一個問題的實例並讓它分配值。您也可能只是在某種查找表中處理此問題,但屬性似乎是允許您向模型添加新屬性並更新單個位置中的映射的最簡單方法。
我在這裏呈現整個模型,其中有100個屬性映射到服務器響應。
public class Question
{
[Map("0")]
public string FooBar { get; set; }
[Map("1")]
public string Id { get; set; }
[Map("2")]
public string Action { get; set; }
[Map("3")]
public string Topic { get; set; }
[Map("4")]
public string Body { get; set; }
[Map("5")]
public string Time { get; set; }
[Map("6")]
public string Query { get; set; }
[Map("7")]
public string Answer { get; set; }
[Map("8")]
public string __8 { get; set; }
[Map("9")]
public string __9 { get; set; }
[Map("10")]
public string __10 { get; set; }
[Map("11")]
public string __11 { get; set; }
[Map("12")]
public string __12 { get; set; }
[Map("13")]
public string __13 { get; set; }
[Map("14")]
public string __14 { get; set; }
[Map("15")]
public string __15 { get; set; }
[Map("16")]
public string __16 { get; set; }
[Map("17")]
public string __17 { get; set; }
[Map("18")]
public string __18 { get; set; }
[Map("19")]
public string __19 { get; set; }
[Map("20")]
public string __20 { get; set; }
[Map("21")]
public string __21 { get; set; }
[Map("22")]
public string __22 { get; set; }
[Map("23")]
public string __23 { get; set; }
[Map("24")]
public string __24 { get; set; }
[Map("25")]
public string __25 { get; set; }
[Map("26")]
public string __26 { get; set; }
[Map("27")]
public string __27 { get; set; }
[Map("28")]
public string __28 { get; set; }
[Map("29")]
public string __29 { get; set; }
[Map("30")]
public string __30 { get; set; }
[Map("31")]
public string __31 { get; set; }
[Map("32")]
public string __32 { get; set; }
[Map("33")]
public string __33 { get; set; }
[Map("34")]
public string __34 { get; set; }
[Map("35")]
public string __35 { get; set; }
[Map("36")]
public string __36 { get; set; }
[Map("37")]
public string __37 { get; set; }
[Map("38")]
public string __38 { get; set; }
[Map("39")]
public string __39 { get; set; }
[Map("40")]
public string __40 { get; set; }
[Map("41")]
public string __41 { get; set; }
[Map("42")]
public string __42 { get; set; }
[Map("43")]
public string __43 { get; set; }
[Map("44")]
public string __44 { get; set; }
[Map("45")]
public string __45 { get; set; }
[Map("46")]
public string __46 { get; set; }
[Map("47")]
public string __47 { get; set; }
[Map("48")]
public string __48 { get; set; }
[Map("49")]
public string __49 { get; set; }
[Map("50")]
public string __50 { get; set; }
[Map("51")]
public string __51 { get; set; }
[Map("52")]
public string __52 { get; set; }
[Map("53")]
public string __53 { get; set; }
[Map("54")]
public string __54 { get; set; }
[Map("55")]
public string __55 { get; set; }
[Map("56")]
public string __56 { get; set; }
[Map("57")]
public string __57 { get; set; }
[Map("58")]
public string __58 { get; set; }
[Map("59")]
public string __59 { get; set; }
[Map("60")]
public string __60 { get; set; }
[Map("61")]
public string __61 { get; set; }
[Map("62")]
public string __62 { get; set; }
[Map("63")]
public string __63 { get; set; }
[Map("64")]
public string __64 { get; set; }
[Map("65")]
public string __65 { get; set; }
[Map("66")]
public string __66 { get; set; }
[Map("67")]
public string __67 { get; set; }
[Map("68")]
public string __68 { get; set; }
[Map("69")]
public string __69 { get; set; }
[Map("70")]
public string __70 { get; set; }
[Map("71")]
public string __71 { get; set; }
[Map("72")]
public string __72 { get; set; }
[Map("73")]
public string __73 { get; set; }
[Map("74")]
public string __74 { get; set; }
[Map("75")]
public string __75 { get; set; }
[Map("76")]
public string __76 { get; set; }
[Map("77")]
public string __77 { get; set; }
[Map("78")]
public string __78 { get; set; }
[Map("79")]
public string __79 { get; set; }
[Map("80")]
public string __80 { get; set; }
[Map("81")]
public string __81 { get; set; }
[Map("82")]
public string __82 { get; set; }
[Map("83")]
public string __83 { get; set; }
[Map("84")]
public string __84 { get; set; }
[Map("85")]
public string __85 { get; set; }
[Map("86")]
public string __86 { get; set; }
[Map("87")]
public string __87 { get; set; }
[Map("88")]
public string __88 { get; set; }
[Map("89")]
public string __89 { get; set; }
[Map("90")]
public string __90 { get; set; }
[Map("91")]
public string __91 { get; set; }
[Map("92")]
public string __92 { get; set; }
[Map("93")]
public string __93 { get; set; }
[Map("94")]
public string __94 { get; set; }
[Map("95")]
public string __95 { get; set; }
[Map("96")]
public string __96 { get; set; }
[Map("97")]
public string __97 { get; set; }
[Map("98")]
public string __98 { get; set; }
[Map("99")]
public string __99 { get; set; }
[Map("100")]
public string __100 { get; set; }
}
現在,在建立第一個連接時,獲取所有屬性及其屬性並將它們緩存到字典中。
Dictionary<string, MapAttribute> properties = typeof(Question).GetProperties().ToDictionary(
property => property.GetCustomAttribute<MapAttribute>().Field,
property =>
{
var attribute = property.GetCustomAttribute<MapAttribute>();
attribute.Property = property;
return attribute;
});
在應用程序的生命週期中只做一次。您將在從服務器獲得的每個響應中重新使用該字典。現在,當您從服務器收到更新時,只需使用該屬性解析它即可。
void Parse(string message, Dictionary<string, MapAttribute> fieldMapping)
{
string[] messageContent = message.Split(':');
var question = new Question();
for (int index = 0; index < messageContent.Length; index++)
{
string field = messageContent[index];
MapAttribute mapping = fieldMapping[field];
index++;
mapping.SetValue(question, messageContent[index]);
}
}
這裏沒有任何真正的花式。我們剛剛使用字典查找和屬性來替換switch語句,以便將映射響應鍵映射到模型屬性。大量減少必須編寫的最終代碼,並讓您在將來使用新屬性更新模型。簡單和容易維護。您可以通過不擔心太多性能來達到此目的,直到性能實際上成爲可衡量的問題。
你能修好你的樣品嗎?字符串'0:7:3:改變話題4:疑問:5:2016092710:19:100:!'顯然是無效的。 – Enigmativity
固定爲0:7:3:已更改主題:4:疑問:5:2016092710:100 :! –
將事情分解到更小的可管理類中並不會讓事情變得複雜。如果有的話,試圖閱讀和理解switch語句如何工作超過99個不同的潛在案例很難遵循和難以理解。我爲IRC客戶端做了這樣的事情,並且實施了一個適當的模式來解決這個問題。有模式可以清理事物。通常,如果您發現模式複雜,您可能沒有以正確的方式使用它。 –