स्वीकृत उत्तर सही ढंग से बताता है कि सूची कैसे घोषित की जानी चाहिए और अधिकांश परिदृश्यों के लिए अत्यधिक अनुशंसित है।
लेकिन मैं एक अलग परिदृश्य में आया, जो पूछे गए प्रश्न को भी कवर करता है। यदि आपको किसी मौजूदा ऑब्जेक्ट सूची का उपयोग करना है, जैसे ViewData["htmlAttributes"]
कि MVC में ? आप इसके गुणों का उपयोग कैसे कर सकते हैं (वे आमतौर पर के माध्यम से बनाए जाते हैंnew { @style="width: 100px", ... }
)?
इस अलग परिदृश्य के लिए मैं आपके साथ साझा करना चाहता हूं जो मुझे पता चला। नीचे दिए गए समाधानों में, मैं निम्नलिखित घोषणा कर रहा हूं nodes
:
List<object> nodes = new List<object>();
nodes.Add(
new
{
Checked = false,
depth = 1,
id = "div_1"
});
1. गतिशील के साथ समाधान
में सी # 4.0 और उच्चतर संस्करण, तो आप बस गतिशील और लिखने पर कास्ट कर सकते:
if (nodes.Any(n => ((dynamic)n).Checked == false))
Console.WriteLine("found not checked element!");
नोट: यह उपयोग कर रहा है देर से बाध्यकारी, जिसका अर्थ है कि यह केवल रनटाइम पर पहचान लेंगे अगर वस्तु एक नहीं है Checked
संपत्ति और एक फेंकता RuntimeBinderException
इस मामले में - इसलिए यदि आप एक गैर-मौजूद इस्तेमाल करने की कोशिश Checked2
संपत्ति आपको निम्न संदेश मिलता है पर क्रम: "'<>f__AnonymousType0<bool,int,string>' does not contain a definition for 'Checked2'"
।
2. प्रतिबिंब के साथ समाधान
प्रतिबिंब के साथ समाधान पुराने और नए C # संकलक संस्करणों के साथ काम करता है । पुराने C # संस्करणों के लिए कृपया इस उत्तर के अंत में संकेत दें।
पृष्ठभूमि
शुरुआती बिंदु के रूप में, मुझे यहां एक अच्छा जवाब मिला । प्रतिबिंब के रूप में अनाम डेटा प्रकार को शब्दकोश में परिवर्तित करने का विचार है। शब्दकोश को गुणों को एक्सेस करना आसान बनाता है, क्योंकि उनके नाम कुंजी के रूप में संग्रहीत किए जाते हैं (आप उन्हें पसंद कर सकते हैंmyDict["myProperty"]
)।
ऊपर दिए गए लिंक में कोड से प्रेरित होकर, मैंने एक विस्तार वर्ग प्रदान किया GetProp
, UnanonymizeProperties
और UnanonymizeListItems
विस्तार विधियों के रूप में, जो गुमनाम संपत्तियों तक पहुंच को आसान बनाता है। इस वर्ग के साथ आप केवल निम्नानुसार क्वेरी कर सकते हैं:
if (nodes.UnanonymizeListItems().Any(n => (bool)n["Checked"] == false))
{
Console.WriteLine("found not checked element!");
}
या आप स्थिति के nodes.UnanonymizeListItems(x => (bool)x["Checked"] == false).Any()
रूप में अभिव्यक्ति का उपयोग कर सकते if
हैं, जो अंतर्निहित रूप से फ़िल्टर करता है और फिर जांचता है कि क्या कोई तत्व वापस आए हैं या नहीं।
"चेक की गई" संपत्ति वाली पहली वस्तु प्राप्त करने और अपनी संपत्ति "गहराई" वापस करने के लिए, आप उपयोग कर सकते हैं:
var depth = nodes.UnanonymizeListItems()
?.FirstOrDefault(n => n.Contains("Checked")).GetProp("depth");
या इससे कम: nodes.UnanonymizeListItems()?.FirstOrDefault(n => n.Contains("Checked"))?["depth"];
नोट: यदि आपके पास उन वस्तुओं की एक सूची है, जिनमें आवश्यक रूप से सभी गुण नहीं हैं (उदाहरण के लिए, कुछ में "चेक की गई संपत्ति" नहीं है), और आप अभी भी "चेक किए गए" मानों के आधार पर एक क्वेरी बनाना चाहते हैं, तो आप कर सकते हैं यह करो:
if (nodes.UnanonymizeListItems(x => { var y = ((bool?)x.GetProp("Checked", true));
return y.HasValue && y.Value == false;}).Any())
{
Console.WriteLine("found not checked element!");
}
यह रोकता है, कि KeyNotFoundException
अगर "चेक की गई" संपत्ति मौजूद नहीं है।
नीचे दिए गए वर्ग में निम्नलिखित विस्तार विधियाँ शामिल हैं:
UnanonymizeProperties
: किसी वस्तु में निहित गुणों को डी-अनॉइज़ करने के लिए उपयोग किया जाता है । यह विधि प्रतिबिंब का उपयोग करती है। यह ऑब्जेक्ट को गुण और उसके मूल्यों वाले शब्दकोश में परिवर्तित करता है।
UnanonymizeListItems
: वस्तुओं की सूची को गुणों से युक्त शब्दकोशों की सूची में बदलने के लिए उपयोग किया जाता है। यह वैकल्पिक रूप से पहले से छानने के लिए एक लंबोदर अभिव्यक्ति हो सकती है ।
GetProp
: दिए गए संपत्ति के नाम से मेल खाते एक एकल मान को वापस करने के लिए उपयोग किया जाता है। KeyNotFoundException (झूठी) के बजाय शून्य मानों (सत्य) के रूप में मौजूदा-मौजूदा गुणों का इलाज करने की अनुमति देता है
उपरोक्त उदाहरणों के लिए, सभी आवश्यक है कि आप नीचे विस्तार वर्ग जोड़ दें:
public static class AnonymousTypeExtensions
{
// makes properties of object accessible
public static IDictionary UnanonymizeProperties(this object obj)
{
Type type = obj?.GetType();
var properties = type?.GetProperties()
?.Select(n => n.Name)
?.ToDictionary(k => k, k => type.GetProperty(k).GetValue(obj, null));
return properties;
}
// converts object list into list of properties that meet the filterCriteria
public static List<IDictionary> UnanonymizeListItems(this List<object> objectList,
Func<IDictionary<string, object>, bool> filterCriteria=default)
{
var accessibleList = new List<IDictionary>();
foreach (object obj in objectList)
{
var props = obj.UnanonymizeProperties();
if (filterCriteria == default
|| filterCriteria((IDictionary<string, object>)props) == true)
{ accessibleList.Add(props); }
}
return accessibleList;
}
// returns specific property, i.e. obj.GetProp(propertyName)
// requires prior usage of AccessListItems and selection of one element, because
// object needs to be a IDictionary<string, object>
public static object GetProp(this object obj, string propertyName,
bool treatNotFoundAsNull = false)
{
try
{
return ((System.Collections.Generic.IDictionary<string, object>)obj)
?[propertyName];
}
catch (KeyNotFoundException)
{
if (treatNotFoundAsNull) return default(object); else throw;
}
}
}
सुझाव: कोड ऊपर उपयोग कर रहा है अशक्त-सशर्त ऑपरेटर, के बाद से सी # संस्करण 6.0 उपलब्ध है - अगर आप के साथ हैं काम कर रहे बड़े सी # संकलक (जैसे सी # 3.0), बस की जगह ?.
द्वारा .
और ?[
द्वारा [
, हर जगह जैसे
var depth = nodes.UnanonymizeListItems()
.FirstOrDefault(n => n.Contains("Checked"))["depth"];
यदि आप पुराने C # कंपाइलर का उपयोग करने के लिए बाध्य नहीं हैं , तो इसे वैसे ही रखें, क्योंकि अशक्त-स्थिति का उपयोग करने से अशक्तता बहुत आसान हो जाती है।
नोट: डायनामिक के साथ अन्य समाधान की तरह, यह समाधान भी देर से बाध्यकारी का उपयोग कर रहा है, लेकिन इस मामले में आपको एक अपवाद नहीं मिल रहा है - यह तत्व नहीं मिलेगा यदि आप एक गैर-मौजूदा संपत्ति की बात कर रहे हैं, जब तक कि जैसा कि आप अशक्त संचालकों को रखते हैं।
कुछ अनुप्रयोगों के लिए क्या उपयोगी हो सकता है कि संपत्ति को समाधान 2 में स्ट्रिंग के माध्यम से संदर्भित किया जाता है, इसलिए इसे पैरामीटर किया जा सकता है।