जवाबों:
MSDN के अनुसार घोषणा से पता चलता है कि यह IDEDIA को लागू कर रहा है:
public sealed class ExpandoObject : IDynamicMetaObjectProvider,
IDictionary<string, Object>, ICollection<KeyValuePair<string, Object>>,
IEnumerable<KeyValuePair<string, Object>>, IEnumerable, INotifyPropertyChanged
आप यह देखने के लिए उपयोग कर सकते हैं कि क्या कोई सदस्य परिभाषित है:
var expandoObject = ...;
if(((IDictionary<String, object>)expandoObject).ContainsKey("SomeMember")) {
// expandoObject.SomeMember exists.
}
एक महत्वपूर्ण अंतर यहां किए जाने के लिए की जरूरत है।
यहां अधिकांश उत्तर एक्सपेंडीओबजेक्ट के लिए विशिष्ट हैं जो प्रश्न में उल्लिखित हैं। लेकिन ASP.Net MVC ViewBag का उपयोग करते समय एक आम उपयोग (और इस सवाल पर उतरने का कारण) है। यह एक कस्टम कार्यान्वयन / डायनामिकऑब्जेक्ट का उपवर्ग है, जो शून्य के लिए किसी भी मनमानी संपत्ति के नाम की जांच करने पर एक अपवाद नहीं फेंकेगा। मान लीजिए कि आप एक संपत्ति घोषित कर सकते हैं जैसे:
@{
ViewBag.EnableThinger = true;
}
फिर मान लीजिए कि आप इसके मूल्य की जांच करना चाहते हैं, और क्या यह सेट भी है - क्या यह मौजूद है। निम्नलिखित मान्य है,, संकलित कर देगा किसी भी अपवाद फेंक नहीं होगा, और आप सही जवाब देता है:
if (ViewBag.EnableThinger != null && ViewBag.EnableThinger)
{
// Do some stuff when EnableThinger is true
}
अब EnableThinger की घोषणा से छुटकारा पाएं। समान कोड संकलित करता है और ठीक से चलता है। प्रतिबिंब की कोई जरूरत नहीं।
ViewBag के विपरीत, ExpandoObject फेंक देगा यदि आप उस संपत्ति पर नल की जांच करते हैं जो मौजूद नहीं है। आपकी dynamic
वस्तुओं में से MVC ViewBag की gentler कार्यक्षमता प्राप्त करने के लिए , आपको गतिशील के कार्यान्वयन का उपयोग करना होगा जो फेंक नहीं है।
आप बस MVC ViewBag में सटीक कार्यान्वयन का उपयोग कर सकते हैं:
. . .
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = ViewData[binder.Name];
// since ViewDataDictionary always returns a result even if the key does not exist, always return true
return true;
}
. . .
आप इसे एमवीसी व्यूज में, एमवीसी व्यूज में बंधे हुए देख सकते हैं:
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/ViewPage.cs
डायनामिक व्यूडैडॉरड के सुशोभित व्यवहार की कुंजी व्यूडैडॉर पर शब्दकोश कार्यान्वयन है, यहां:
public object this[string key]
{
get
{
object value;
_innerDictionary.TryGetValue(key, out value);
return value;
}
set { _innerDictionary[key] = value; }
}
https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/ViewDataDictionary.cs
दूसरे शब्दों में, यह हमेशा सभी कुंजी के लिए एक मूल्य देता है, फिर चाहे इसमें कुछ भी हो - यह केवल शून्य है जब कुछ भी नहीं है। लेकिन, ViewDataDictionary के MVC के मॉडल से बंधा होने का बोझ है, इसलिए यह बेहतर है कि एमवीसी व्यू के बाहर उपयोग के लिए सिर्फ सुंदर शब्दकोश भागों को छीन लिया जाए।
यह वास्तव में यहां सभी हिम्मत को पोस्ट करने के लिए बहुत लंबा है - इसमें से अधिकांश सिर्फ IDEDIA को लागू कर रहे हैं - लेकिन यहां एक गतिशील वस्तु (वर्ग DDict
) है जो उन गुणों पर शून्य जांच के लिए नहीं फेंकती है जिन्हें घोषित नहीं किया गया है, गिथूब पर:
https://github.com/b9chris/GracefulDynamicDictionary
यदि आप इसे अपने प्रोजेक्ट में NuGet के माध्यम से जोड़ना चाहते हैं, तो इसका नाम GracefulDynamicDictionary है ।
मैंने हाल ही में एक समान प्रश्न का उत्तर दिया: मैं गतिशील वस्तु के सदस्यों पर कैसे प्रतिबिंबित करूं?
शीघ्र ही, ExpandoObject एकमात्र गतिशील वस्तु नहीं है जो आपको मिल सकती है। प्रतिबिंब स्थैतिक प्रकारों के लिए काम करेगा (वे प्रकार जो ID DynamicsicMetaObjectProvider को लागू नहीं करते हैं)। इस इंटरफ़ेस को लागू करने वाले प्रकारों के लिए, प्रतिबिंब मूल रूप से बेकार है। ExpandoObject के लिए, आप बस जांच सकते हैं कि क्या संपत्ति को अंतर्निहित शब्दकोश में एक कुंजी के रूप में परिभाषित किया गया है। अन्य कार्यान्वयन के लिए, यह चुनौतीपूर्ण हो सकता है और कभी-कभी एकमात्र तरीका अपवादों के साथ काम करना है। जानकारी के लिए, ऊपर दिए गए लिंक का पालन करें।
अद्यतन: आप प्रतिनिधियों का उपयोग कर सकते हैं और गतिशील वस्तु संपत्ति से एक मूल्य प्राप्त करने का प्रयास कर सकते हैं यदि यह मौजूद है। यदि कोई संपत्ति नहीं है, तो केवल अपवाद को पकड़ें और झूठे वापस करें।
देखिए, यह मेरे लिए ठीक है:
class Program
{
static void Main(string[] args)
{
dynamic userDynamic = new JsonUser();
Console.WriteLine(IsPropertyExist(() => userDynamic.first_name));
Console.WriteLine(IsPropertyExist(() => userDynamic.address));
Console.WriteLine(IsPropertyExist(() => userDynamic.last_name));
}
class JsonUser
{
public string first_name { get; set; }
public string address
{
get
{
throw new InvalidOperationException("Cannot read property value");
}
}
}
static bool IsPropertyExist(GetValueDelegate getValueMethod)
{
try
{
//we're not interesting in the return value. What we need to know is whether an exception occurred or not
getValueMethod();
return true;
}
catch (RuntimeBinderException)
{
// RuntimeBinderException occurred during accessing the property
// and it means there is no such property
return false;
}
catch
{
//property exists, but an exception occurred during getting of a value
return true;
}
}
delegate string GetValueDelegate();
}
कोड का आउटपुट निम्न है:
True
True
False
IsPropertyExist
। इस उदाहरण में, आप जानते हैं कि कोई एक फेंक सकता है InvalidOperationException
। व्यवहार में, आपके पास कोई विचार नहीं है कि किस अपवाद को फेंका जा सकता है। कार्गो पंथ का मुकाबला करने के लिए +1।
मैं एक विस्तार विधि बनाना चाहता था ताकि मैं कुछ ऐसा कर सकूं:
dynamic myDynamicObject;
myDynamicObject.propertyName = "value";
if (myDynamicObject.HasProperty("propertyName"))
{
//...
}
... लेकिन आप ExpandoObject
C # 5 प्रलेखन ( यहां अधिक जानकारी ) के अनुसार एक्सटेंशन नहीं बना सकते ।
इसलिए मैंने एक क्लास हेल्पर का निर्माण किया:
public static class ExpandoObjectHelper
{
public static bool HasProperty(ExpandoObject obj, string propertyName)
{
return ((IDictionary<String, object>)obj).ContainsKey(propertyName);
}
}
इसके प्रयेाग के लिए:
// If the 'MyProperty' property exists...
if (ExpandoObjectHelper.HasProperty(obj, "MyProperty"))
{
...
}
आप टाइप प्रॉपर सेट के लिए रिफ्लेक्शन का उपयोग क्यों नहीं करना चाहते हैं? ऐशे ही
dynamic v = new Foo();
Type t = v.GetType();
System.Reflection.PropertyInfo[] pInfo = t.GetProperties();
if (Array.Find<System.Reflection.PropertyInfo>(pInfo, p => { return p.Name == "PropName"; }). GetValue(v, null) != null))
{
//PropName initialized
}
यह एक्सटेंशन विधि किसी संपत्ति के अस्तित्व की जाँच करती है और फिर मान या अशक्तता लौटाती है। यह उपयोगी है यदि आप नहीं चाहते हैं कि आपके आवेदन अनावश्यक अपवादों को फेंक दें, तो कम से कम आप मदद कर सकते हैं।
public static object Value(this ExpandoObject expando, string name)
{
var expandoDic = (IDictionary<string, object>)expando;
return expandoDic.ContainsKey(name) ? expandoDic[name] : null;
}
अगर इस तरह इस्तेमाल किया जा सकता है:
// lookup is type 'ExpandoObject'
object value = lookup.Value("MyProperty");
या यदि आपका स्थानीय वैरिएबल 'डायनेमिक' है, तो आपको इसे पहले ExpandoObject पर डालना होगा।
// lookup is type 'dynamic'
object value = ((ExpandoObject)lookup).Value("PropertyBeingTested");
आपके उपयोग के मामले के आधार पर, यदि अशक्त को अपरिभाषित के रूप में एक ही माना जा सकता है, तो आप अपने एक्सपेंडेओऑब्जेक्ट को एक डायनेमिकजोनऑब्जेक्ट में बदल सकते हैं।
dynamic x = new System.Web.Helpers.DynamicJsonObject(new ExpandoObject());
x.a = 1;
x.b = 2.50;
Console.WriteLine("a is " + (x.a ?? "undefined"));
Console.WriteLine("b is " + (x.b ?? "undefined"));
Console.WriteLine("c is " + (x.c ?? "undefined"));
आउटपुट:
a is 1
b is 2.5
c is undefined
(authorDynamic as ExpandoObject).Any(pair => pair.Key == "YourProp");
हे लोग सब कुछ के लिए परावर्तन का उपयोग करना बंद कर देते हैं, इसमें बहुत सारे सीपीयू चक्र खर्च होते हैं।
यहाँ समाधान है:
public class DynamicDictionary : DynamicObject
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get
{
return dictionary.Count;
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name;
if (!dictionary.TryGetValue(binder.Name, out result))
result = "undefined";
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
इसको आजमाओ
public bool PropertyExist(object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName) != null;
}
dynamic
(हमेशा रिटर्न null
)।
data.myProperty
; यह जाँच करता है कि क्याtypeof data.myProperty
रिटर्न। यह सही है किdata.myProperty
मौजूद हो सकता है और इसे सेट किया जा सकता हैundefined
, लेकिन उस स्थिति में,typeof
इसके अलावा कुछ और लौटाएगा"undefined"
। तो यह कोड काम करता है।