我认为你担心在这种情况下不成熟的优化。一般的经验法则是 - 除非性能问题实际可衡量,否则不要优化。
考虑到这一点,这个问题可以在一个相当优雅的庄园中解决。我将使用一点缓存反射,这样我只需拉动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客户端做了这样的事情,并且实施了一个适当的模式来解决这个问题。有模式可以清理事物。通常,如果您发现模式复杂,您可能没有以正确的方式使用它。 –