2013-05-13 7 views
9

मैं एक प्रोजेक्ट पर काम कर रहा हूं और मेरा काम एक उन्नत खोज और फ़िल्टरिंग विकल्प जोड़ना है जो उपयोगकर्ताओं को विंडोज़ इवेंट्स की सूची से वांछित परिणाम पूछने की अनुमति देता है जैसा वे चाहते हैं।नेस्टेड स्विच स्टेटमेंट्स: आर्किटेक्चरल डिज़ाइन इश्यू

विचार प्रत्येक विंडोज ईवेंट लॉग ऐसे 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 पदानुक्रम की जटिलता को कम करने या कोड को अधिक सामान्य बनाकर एक तरीका ढूंढकर? किसी भी मदद/सुझाव की सराहना की है।

+0

आईएमओ, जो एकाधिक प्रेषण (विज़िटर पैटर्न) के लिए उम्मीदवार की तरह दिखता है। हालांकि मैं लोगों से अधिक स्मार्ट लोगों के जवाब छोड़ दूंगा :) –

+1

आपकी डेटा एक्सेस रणनीति क्या है? यदि आप LINQ से SQL या LINQ से इकाइयों का उपयोग कर रहे हैं तो यह 'IQueryable ' इंटरफ़ेस का उपयोग कर वास्तव में सरल (और सुरुचिपूर्ण) भी हो सकता है। – Yuck

+0

इवेंट लॉग @Yuck 'System.Diagnostics.EventLog.GetEventLogs द्वारा()' लौटा दिए जाते हैं, और 'EventLogItem' (कस्टम प्रकार) की एक सूची उन लोगों से बनाया जाता है, और अंत में एक' ListView' नियंत्रण करने के लिए बाध्य कर रहे हैं। 'IQueryable' वह है जो मेरे बारे में एक झुकाव था, लेकिन यह सुनिश्चित नहीं था कि इसे कैसे कार्यान्वित/उपयोग किया जाए। – PoweredByOrange

उत्तर

1

मैं तुम्हें दो स्विच बयान की जरूरत है लगता है, लेकिन वे नेस्ट किए जाने की जरूरत नहीं है। आप ऑपरेशन को किसी भी प्रकार की ऑब्जेक्ट पर सामान्य रूप से काम करने के लिए अलग कर सकते हैं, और फिर उस ऑब्जेक्ट को पास कर सकते हैं जिसे आप रनटाइम पर खोज रहे हैं।

public static class SearchProvider 
{ 
    static Func<object, bool> GetSearchMethod(SelectorOperator selectorOperator, string conditionFieldValue) 
    { 
     switch (selectorOperator) 
     { 
      //strings 
      case SelectorOperator.Contains: 
       return new Func<object, bool>(s => s.ToString().ToLower().Contains(conditionFieldValue)); 
      case SelectorOperator.StartsWith: 
       return new Func<object, bool>(s => s.ToString().ToLower().StartsWith(conditionFieldValue)); 
      case SelectorOperator.EndsWith: 
       return new Func<object, bool>(s => s.ToString().ToLower().EndsWith(conditionFieldValue)); 
      case SelectorOperator.Is: 
       return new Func<object, bool>(s => string.Equals(s.ToString(), conditionFieldValue, StringComparison.OrdinalIgnoreCase)); 

      //numbers 
      case SelectorOperator.Equals: 
       return new Func<object, bool>(n => (long)n == long.Parse(conditionFieldValue)); 
      case SelectorOperator.IsGreaterThan: 
       return new Func<object, bool>(n => (long)n > long.Parse(conditionFieldValue)); 
      case SelectorOperator.IsLessThan: 
       return new Func<object, bool>(n => (long)n < long.Parse(conditionFieldValue)); 

      //type 
      case SelectorOperator.TypeIs: 
       return new Func<object, bool>(t => (EventLogEntryType)t == (EventLogEntryType)Enum.Parse(typeof(EventLogEntryType), conditionFieldValue)); 
      case SelectorOperator.TypeIsNot: 
       return new Func<object, bool>(t => (EventLogEntryType)t != (EventLogEntryType)Enum.Parse(typeof(EventLogEntryType), conditionFieldValue)); 

      default: 
       throw new Exception("Unknown selector operator"); 
     } 
    } 

    private static List<EventLogItem> SearchAll(List<EventLogItem> currentLogs, SearchQuery query) 
    { 
     foreach (SearchCondition condition in query.Conditions) 
     { 
      var search = GetSearchMethod(condition.SelectorOperator, condition.FieldValue as string); 
      switch (condition.FieldName) 
      { 
       case FieldItem.Category: 
        currentLogs = currentLogs.Where(item => search(item.Category)).ToList(); 
        break; 
       case FieldItem.InstanceID: 
        currentLogs = currentLogs.Where(item => search(item.InstanceID)).ToList(); 
        break; 
       case FieldItem.LogName: 
        currentLogs = currentLogs.Where(item => search(item.LogName)).ToList(); 
        break; 
       case FieldItem.Message: 
        currentLogs = currentLogs.Where(item => search(item.Message)).ToList(); 
        break; 
       case FieldItem.Number: 
        currentLogs = currentLogs.Where(item => search(item.Number)).ToList(); 
        break; 
       case FieldItem.Source: 
        currentLogs = currentLogs.Where(item => search(item.Source)).ToList(); 
        break; 
       case FieldItem.Type: 
        currentLogs = currentLogs.Where(item => search(item.Type)).ToList(); 
        break; 
      } 
     } 
     return currentLogs; 
    } 
} 

नोट मैं इस देर से, क्योंकि ऐसा सर्वर दुर्घटनाग्रस्त हो गया, तो मैं बिस्तर :(
इसलिए यह @ dasblinkenlight के जवाब के समान है के लिए चला गया था।

2

इस प्रकार के कार्य को संभालने का मानक तरीका एक कस्टम IQueryable प्रदाता बनाना होगा और केवल LINQ का उपयोग करना होगा। सचमुच, आप जिस भी ऑपरेशन की तलाश में हैं वह LINQ अभिव्यक्तियों के माध्यम से एक मानक विस्तारशीलता तंत्र है। मूल विचार यह है कि आपके पास ExpressionVisitor कार्यान्वयन होगा जो एक विशाल स्विच स्टेटमेंट के बजाय प्रत्येक पुनर्लेखन नियम लागू करता है। चूंकि आप जितना चाहें उतने अभिव्यक्ति आगंतुकों का उपयोग कर सकते हैं, इसलिए आपका रखरखाव और एक्स्टेंसिबिलिटी लागत कम हो जाती है।

यदि आप इस दृष्टिकोण को लेना चाहते हैं तो मैं IQToolkit और मैट वॉरेन की Building an IQueryable ब्लॉग श्रृंखला को देखने की अत्यधिक अनुशंसा करता हूं।

+0

ट्यूटोरियल पूरी तरह से है लेकिन मेरे लिए थोड़ा जटिल है, क्या आपको पता है कि कहीं भी कोई आसान (लेकिन एक ही समय में व्यावहारिक) ट्यूटोरियल उपलब्ध है? मुझे Google पर कोई नहीं मिला। धन्यवाद। – PoweredByOrange

2

घोंसले से बचने और संबंधित डुप्लिकेशन से बचने का एक तरीका कोड के उन हिस्सों को अलग करना है जो उस पर संचालन करने वाले कोड के हिस्सों से मूल्य निकालते हैं। यहाँ एक छोटा सा उदाहरण है कि तकनीक का उदाहरण देकर स्पष्ट करना चाहिए:

Func<EventLogEntry,string> getString = null; 
Func<EventLogEntry,int> getInt32 = null; 
... 
switch (condition.FieldName) { 
    case FieldItem.Category: getString = e => e.Category; break; 
    case FieldItem.Message: getString = e => e.Message; break; 
    case FieldItem.Number: getInt32 = e => e.Number; break; 
    default:     throw new ApplicationException("Unsupported field"); 
} 
switch (condition.SelectorOperator) { 
    case SelectorOperator.Contains: 
     currentLogs = currentLogs.Where(item => getString(item).ToLower().Contains(condition.FieldValue as string)).ToList(); 
    break; 
    case SelectorOperator.EndsWith: 
     currentLogs = currentLogs.Where(item => getString(item).ToLower().EndsWith(condition.FieldValue as string)).ToList(); 
    break; 
    case SelectorOperator.Is: 
     currentLogs = currentLogs.Where(item => string.Equals(getString(item), condition.FieldValue as string, StringComparison.OrdinalIgnoreCase)).ToList(); 
    break; 
    case SelectorOperator.StartsWith: 
     currentLogs = currentLogs.Where(item => getString(item).ToLower().StartsWith(condition.FieldValue as string)).ToList(); 
    break; 
    case SelectorOperator.Equals: 
     currentLogs = currentLogs.Where(item => getInt32(item) == int.Parse(condition.FieldValue as string)).ToList(); 
    break; 
    case SelectorOperator.IsGreaterThan: 
     currentLogs = currentLogs.Where(item => getInt32(item) > int.Parse(condition.FieldValue as string)).ToList(); 
    break; 
    case SelectorOperator.IsLessThan: 
     currentLogs = currentLogs.Where(item => getInt32(item) < int.Parse(condition.FieldValue as string)).ToList(); 
    break; 
} 

एक नया स्रोत क्षेत्र अब पहले switch के लिए एक और case जोड़ने जरूरत पर जोर देता जोड़ रहा है; एक प्रकार के लिए एक नया ऑपरेशन जोड़ने के लिए दूसरे switch में केवल एक नया case की आवश्यकता होगी, इस प्रकार आपके कोड में "रखरखाव बिंदु" की संख्या कम हो जाएगी।

+0

यह मेरे प्रारंभिक कार्यान्वयन से निश्चित रूप से एक बेहतर समाधान है और कार्यक्रम की रखरखाव में काफी वृद्धि करता है। हालांकि, दूसरों को 'IQueryable' और' ExpressionVisitor 'का उपयोग करने का सुझाव देने के बाद, मैं यह देखने की कोशिश कर रहा हूं कि मैं अपनी समस्या के लिए उन्हें कैसे लागू कर सकता हूं। हालांकि आपका जवाब निश्चित रूप से एक महान प्रारंभिक बिंदु है। धन्यवाद! – PoweredByOrange

+2

@ programmer93 ['IQueryProvider'] (http://msdn.microsoft.com/en-us/library/system.linq.iqueryprovider.aspx) पर आधारित एक दृष्टिकोण .NET पर्यावरण के साथ बेहतर एकीकरण प्रदान करेगा, लेकिन यह काफी जटिल है (मैंने उनमें से कुछ को लागू किया है, और इसमें बहुत सी शिक्षाएं हुईं - यहां तक ​​कि LINQ अभिव्यक्तियों के कामकाजी ज्ञान के शीर्ष पर)। – dasblinkenlight

+0

हम्म ... अच्छा मुझे यह सीखने में कोई दिक्कत नहीं होगी, जब मैं LINQ की बात करता हूं तो मुझे बहुत जानकारी नहीं है, लेकिन मुझे लगता है कि वे बेहतर प्रोग्राम लिखने में बेहद उपयोगी हो सकते हैं इसलिए मुझे उन्हें किसी बिंदु पर सीखना होगा।लेकिन दूसरी तरफ, आप शायद सही हैं, मुझे वर्तमान में जो कुछ भी है उससे ज्यादा जटिल बनाने की आवश्यकता नहीं है, क्योंकि Windows EventLogs गुण नियमित आधार पर नहीं बदला जाएगा :) आपकी सलाह के लिए धन्यवाद, मैं इसे मानेंगे। – PoweredByOrange

1

मुझे समझ नहीं आता क्यों लोग IQueryable दृष्टिकोण का सुझाव मैंने हमेशा सोचा कि IQueryable का उपयोग सी # क्वेरी को एसक्यूएल (SELECT स्टेटमेंट) या एक्सएमएल (एक्सक्वियर) जैसी किसी अन्य तकनीक में एक क्वेरी में बदलने के लिए किया जाता है, ताकि इसे किसी भी तकनीक के बारे में जानने के बिना उचित स्थान पर निष्पादित किया जा सके। क्वेरी को बदल दिया गया है (आपके द्वारा डेवलपर/प्रोग्रामर के रूप में और न ही आपके कोड द्वारा - उस टी को कोई तंग युग्मन नहीं chnology)।

के बाद से आपकी क्वेरी सी # में निष्पादित हो रहा है /। NET कोड, वहाँ IQueryable के लिए कोई जरूरत नहीं है।

यदि, उदाहरण के लिए, आप EventLog सेवा की मूल क्वेरीिंग क्षमताओं का उपयोग करेंगे, तो C# LINQ को क्वेरी स्ट्रिंग या किसी अन्य फ़ॉर्म में बदलने के लिए IQueryable को कार्यान्वित करना बहुत अच्छा होगा, जो EventLog सेवा समझता है और निष्पादित करता है।

मेरे लिए, यह समस्या, चेनिंग विधेय द्वारा समग्र विधेय बनाने की एक समस्या की तरह लग रहा है, ताकि समग्र विधेय LINQ में इस्तेमाल किया जा सकता कहाँ बयान।

यह निर्भर करता है कि कैसे सामान्य आप अपने समाधान होना चाहता हूँ, लेकिन यहाँ एक संभावित क्रियान्वयन जो काफी हद तक प्रकार निष्कर्ष और लैम्ब्डा बंद का उपयोग करता है समग्र विधेय बनाने के लिए है:

class Predicate<T> 
{ 
    public static Func<T, bool> Or(params Func<T, bool>[] predicates) 
    { 
     return item => predicates.Any(p => p(item)); 
    } 

    public static Func<T, bool> And(params Func<T, bool>[] predicates) 
    { 
     return item => predicates.All(p => p(item)); 
    } 

    #region Generic predicates 

    public static Func<T, bool> Is<TValue>(Func<T, TValue> selector, string value) where TValue : IEquatable<TValue> 
    { 
     return item => GetEqualityComparer<TValue>().Equals(selector(item), Parse<TValue>(value)); 
    } 

    public static Func<T, bool> IsNot<TValue>(Func<T, TValue> selector, string value) where TValue : IEquatable<TValue> 
    { 
     return item => !Is(selector, value)(item); 
    } 

    public static Func<T, bool> IsLessThan<TValue>(Func<T, TValue> selector, string value) where TValue : IComparable<TValue> 
    { 
     return item => GetComparer<TValue>().Compare(selector(item), Parse<TValue>(value)) < 0; 
    } 

    public static Func<T, bool> IsLessThanOrEqualTo<TValue>(Func<T, TValue> selector, string value) where TValue : IComparable<TValue> 
    { 
     return item => GetComparer<TValue>().Compare(selector(item), Parse<TValue>(value)) <= 0; 
    } 

    public static Func<T, bool> IsGreaterThan<TValue>(Func<T, TValue> selector, string value) where TValue : IComparable<TValue> 
    { 
     return item => !IsLessThanOrEqualTo(selector, value)(item); 
    } 

    public static Func<T, bool> IsGreaterThanOrEqualTo<TValue>(Func<T, TValue> selector, string value) where TValue : IComparable<TValue> 
    { 
     return item => !IsLessThan(selector, value)(item); 
    } 

    public static Func<T, bool> IsBetween<TValue>(Func<T, TValue> selector, string lower, string higher) where TValue : IComparable<TValue> 
    { 
     return item => IsGreaterThan(selector, lower)(item) && IsLessThan(selector, higher)(item); 
    } 

    #endregion 

    #region String specialized predicates 

    public static Func<T, bool> Contains(Func<T, string> selector, string value) 
    { 
     return item => selector(item).IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0; 
    } 

    public static Func<T, bool> StartsWith(Func<T, string> selector, string value) 
    { 
     return item => selector(item).StartsWith(value, StringComparison.OrdinalIgnoreCase); 
    } 

    public static Func<T, bool> EndsWith(Func<T, string> selector, string value) 
    { 
     return item => selector(item).EndsWith(value, StringComparison.OrdinalIgnoreCase); 
    } 

    #endregion 

    private static IEqualityComparer<TValue> GetEqualityComparer<TValue>() 
    { 
     // If value type is string, use OrdinalIgnoreCase equality comparer. 
     return typeof(TValue) == typeof(string) ? (IEqualityComparer<TValue>)StringComparer.OrdinalIgnoreCase : EqualityComparer<TValue>.Default; 
    } 

    private static IComparer<TValue> GetComparer<TValue>() 
    { 
     // If value type is string, use OrdinalIgnoreCase comparer. 
     return typeof(TValue) == typeof(string) ? (IComparer<TValue>)StringComparer.OrdinalIgnoreCase : Comparer<TValue>.Default; 
    } 

    private static TValue Parse<TValue>(string value) 
    { 
     // We need special handling for Enum type since, unfortunately, System.String doesn't handle conversion to Enum type in its IConvertible.ToType implementation. 
     // All other used types (string, DateTime, int, long) are supported by Convert class. 
     return (TValue)(typeof(TValue).IsEnum ? Enum.Parse(typeof(TValue), value) : Convert.ChangeType(value, typeof(TValue), CultureInfo.InvariantCulture)); 
    } 
} 

// For easier typing, no need to explicitly specify type. 
class EventLogPredicate : Predicate<EventLogItem> 
{ 
} 

और यहाँ आप इसे कैसे उपयोग कर सकते हैं:

var items = new List<EventLogItem>() 
{ 
    new EventLogItem() { LogName = "First" }, 
    new EventLogItem() { LogName = "Second bla", Number = 100 }, 
    new EventLogItem() { LogName = "Third bla", Number = 25 }, 
    new EventLogItem() { LogName = "Fourth", Number = 25 } 
}; 

var predicate = EventLogPredicate.And(EventLogPredicate.Contains(item => item.LogName, "bla"), EventLogPredicate.IsLessThan(item => item.Number, "50")); 

var filteredItems = items.Where(predicate).ToArray(); 
+0

मुझे यह दृष्टिकोण पसंद है, लेकिन शर्तें कस्टम प्रकार हैं, और मुझे उनके माध्यम से पुनरावृत्ति करने की आवश्यकता है, इसलिए मुझे यकीन नहीं है कि यह 'var predicate = EventLogPredicate.And (EventLogPredicate.Contains (item => item.LogName) के साथ कैसे करें , "bla"), EventLogPredicate.IsLessThan (item => item.Number, "50")); 'क्योंकि मैं नहीं प्राप्त कर सकता हूं और यह निर्धारित कर सकता हूं कि शर्तों के बिना पहले क्या चल रहा है। – PoweredByOrange

संबंधित मुद्दे