मैं एक प्रोजेक्ट पर काम कर रहा हूं और मेरा काम एक उन्नत खोज और फ़िल्टरिंग विकल्प जोड़ना है जो उपयोगकर्ताओं को विंडोज़ इवेंट्स की सूची से वांछित परिणाम पूछने की अनुमति देता है जैसा वे चाहते हैं।नेस्टेड स्विच स्टेटमेंट्स: आर्किटेक्चरल डिज़ाइन इश्यू
विचार प्रत्येक विंडोज ईवेंट लॉग ऐसे LogName
, Source
, CreatedDate
, Message
, Number
, आदि (FieldItem enum का हिस्सा) के रूप में कई गुण है है। कुल मिलाकर, चार संभावित डेटा प्रकार: String
, DateTime
, Integral (Int/Long)
, और EventEntryType
हैं। इन चार डेटा प्रकारों में से प्रत्येक का चयनकर्ता ऑपरेंड का अपना संग्रह है (का चयनकर्ताऑपरेटर enum)।
public static class SearchProvider
{
public static List<EventLogItem> SearchInLogs(List<EventLogItem> currentLogs, SearchQuery query)
{
switch (query.JoinType)
{
case ConditionJoinType.All:
return SearchAll(currentLogs, query);
case ConditionJoinType.Any:
return SearchAny(currentLogs, query);
default:
return null;
}
}
private static List<EventLogItem> SearchAll(List<EventLogItem> currentLogs, SearchQuery query)
{
foreach (SearchCondition condition in query.Conditions)
{
switch (condition.FieldName)
{
case FieldItem.Category:
switch (condition.SelectorOperator)
{
case SelectorOperator.Contains:
currentLogs = currentLogs.Where(item => item.Category.ToLower().Contains(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.EndsWith:
currentLogs = currentLogs.Where(item => item.Category.ToLower().EndsWith(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.Is:
currentLogs = currentLogs.Where(item => string.Equals(item.Category, condition.FieldValue as string, StringComparison.OrdinalIgnoreCase)).ToList();
break;
case SelectorOperator.StartsWith:
currentLogs = currentLogs.Where(item => item.Category.ToLower().StartsWith(condition.FieldValue as string)).ToList();
break;
}
break;
case FieldItem.InstanceID:
switch (condition.SelectorOperator)
{
case SelectorOperator.Equals:
currentLogs = currentLogs.Where(item => item.InstanceID == long.Parse(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.IsGreaterThan:
currentLogs = currentLogs.Where(item => item.InstanceID > long.Parse(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.IsLessThan:
currentLogs = currentLogs.Where(item => item.InstanceID < long.Parse(condition.FieldValue as string)).ToList();
break;
}
break;
case FieldItem.LogName:
switch (condition.SelectorOperator)
{
case SelectorOperator.Contains:
currentLogs = currentLogs.Where(item => item.LogName.ToLower().Contains(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.EndsWith:
currentLogs = currentLogs.Where(item => item.LogName.ToLower().EndsWith(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.Is:
currentLogs = currentLogs.Where(item => string.Equals(item.LogName, condition.FieldValue as string, StringComparison.OrdinalIgnoreCase)).ToList();
break;
case SelectorOperator.StartsWith:
currentLogs = currentLogs.Where(item => item.LogName.ToLower().StartsWith(condition.FieldValue as string)).ToList();
break;
}
break;
case FieldItem.Message:
switch (condition.SelectorOperator)
{
case SelectorOperator.Contains:
currentLogs = currentLogs.Where(item => item.Message.ToLower().Contains(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.EndsWith:
currentLogs = currentLogs.Where(item => item.Message.ToLower().EndsWith(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.Is:
currentLogs = currentLogs.Where(item => string.Equals(item.Message, condition.FieldValue as string, StringComparison.OrdinalIgnoreCase)).ToList();
break;
case SelectorOperator.StartsWith:
currentLogs = currentLogs.Where(item => item.Message.ToLower().StartsWith(condition.FieldValue as string)).ToList();
break;
}
break;
case FieldItem.Number:
switch (condition.SelectorOperator)
{
case SelectorOperator.Equals:
currentLogs = currentLogs.Where(item => item.Number == int.Parse(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.IsGreaterThan:
currentLogs = currentLogs.Where(item => item.Number > int.Parse(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.IsLessThan:
currentLogs = currentLogs.Where(item => item.Number < int.Parse(condition.FieldValue as string)).ToList();
break;
}
break;
case FieldItem.Source:
switch (condition.SelectorOperator)
{
case SelectorOperator.Contains:
currentLogs = currentLogs.Where(item => item.Source.ToLower().Contains(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.EndsWith:
currentLogs = currentLogs.Where(item => item.Source.ToLower().EndsWith(condition.FieldValue as string)).ToList();
break;
case SelectorOperator.Is:
currentLogs = currentLogs.Where(item => string.Equals(item.Source, condition.FieldValue as string, StringComparison.OrdinalIgnoreCase)).ToList();
break;
case SelectorOperator.StartsWith:
currentLogs = currentLogs.Where(item => item.Source.ToLower().StartsWith(condition.FieldValue as string)).ToList();
break;
}
break;
case FieldItem.Type:
switch (condition.SelectorOperator)
{
case SelectorOperator.Is:
currentLogs = currentLogs.Where(item => item.Type == (EventLogEntryType)Enum.Parse(typeof(EventLogEntryType), condition.FieldValue as string)).ToList();
break;
case SelectorOperator.IsNot:
currentLogs = currentLogs.Where(item => item.Type != (EventLogEntryType)Enum.Parse(typeof(EventLogEntryType), condition.FieldValue as string)).ToList();
break;
}
break;
}
}
return currentLogs;
}
एक नमूना क्वेरी इस प्रकार दिखाई देंगे:
इस विचार के मेरे प्रारंभिक कार्यान्वयन यह है: यहाँ एक चित्र है आप कैसे समग्र संरचना की तरह लग रहा का एक बेहतर विचार दे रहा है :
स्थिति चयनकर्ता:
All of the conditions are met
स्थितियां:
LogName Is "Application"
Message Contains "error"
Type IsNot "Information"
InstanceID IsLessThan 1934
आप देख सकते हैं, SearchAll()
विधि नेस्टेड switch
बयानों की वजह से काफी लंबी और बहुत योग्य नहीं है। कोड काम करता है, हालांकि, मुझे लगता है कि यह इस डिजाइन को लागू करने का सबसे शानदार तरीका नहीं है। क्या इस समस्या से संपर्क करने का कोई बेहतर तरीका है? शायद switch
पदानुक्रम की जटिलता को कम करने या कोड को अधिक सामान्य बनाकर एक तरीका ढूंढकर? किसी भी मदद/सुझाव की सराहना की है।
आईएमओ, जो एकाधिक प्रेषण (विज़िटर पैटर्न) के लिए उम्मीदवार की तरह दिखता है। हालांकि मैं लोगों से अधिक स्मार्ट लोगों के जवाब छोड़ दूंगा :) –
आपकी डेटा एक्सेस रणनीति क्या है? यदि आप LINQ से SQL या LINQ से इकाइयों का उपयोग कर रहे हैं तो यह 'IQueryable' इंटरफ़ेस का उपयोग कर वास्तव में सरल (और सुरुचिपूर्ण) भी हो सकता है। –
Yuck
इवेंट लॉग @Yuck 'System.Diagnostics.EventLog.GetEventLogs द्वारा()' लौटा दिए जाते हैं, और 'EventLogItem' (कस्टम प्रकार) की एक सूची उन लोगों से बनाया जाता है, और अंत में एक' ListView' नियंत्रण करने के लिए बाध्य कर रहे हैं। 'IQueryable' वह है जो मेरे बारे में एक झुकाव था, लेकिन यह सुनिश्चित नहीं था कि इसे कैसे कार्यान्वित/उपयोग किया जाए। – PoweredByOrange