ExpandoObject- তে কোনও সম্পত্তি বিদ্যমান থাকলে কীভাবে সনাক্ত করবেন?


188

জাভাস্ক্রিপ্টে আপনি অনির্ধারিত কীওয়ার্ড ব্যবহার করে কোনও সম্পত্তি সংজ্ঞাযুক্ত কিনা তা সনাক্ত করতে পারেন:

if( typeof data.myProperty == "undefined" ) ...

আপনি কীভাবে এটি সি # তে করবেন ExpandoObjectএবং কোনও ব্যতিক্রম ছাড়াই গতিশীল কীওয়ার্ডটি ব্যবহার করবেন ?


5
@ কোডইনচাউস: নোট করুন যে প্রদর্শিত কোডটি মানটি পরীক্ষা করে না data.myProperty; এটি কি typeof data.myPropertyফিরে আসে তা পরীক্ষা করে । এটি সঠিক যে data.myPropertyবিদ্যমান থাকতে পারে এবং সেট করা যেতে পারে undefined, তবে সেই ক্ষেত্রে, typeofব্যতীত অন্য কিছু ফিরে আসবে "undefined"। সুতরাং এই কোড কাজ করে।
আসমুন্ড এলদুয়েট

উত্তর:


181

এমএসডিএন অনুসারে ঘোষণাপত্রটি দেখায় যে এটি আইডি অভিধান প্রয়োগ করছে:

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.
}

3
এই চেকটিকে আরও সহজ করার জন্য, আমি ট্রাইগেটভ্যালুকে ওভারলোড করেছি এবং সম্পত্তিটিকে সংজ্ঞায়িত না করা হলে রিটার্ন মানটিকে "অপরিজ্ঞাত" করে সেট করে সর্বদা সত্য করে ফেলি। if (someObject.someParam! = "অপরিজ্ঞাত") ... এবং এটি কাজ করে :)
সফটলিয়ন

এছাড়াও সম্ভব :), তবে আমি মনে করি আপনি ওভারলোডের পরিবর্তে "ওভাররাইড" বোঝালেন।
ডাইকাম

হাঁ। আমি আবার "অপরিবর্তিত" অন্যত্র তৈরি করা একটি বিশেষ অবজেক্টের কনস্ট মানে পরিবর্তন করেছি। এটি
ingালাই

1
আমি বিশ্বাস করি যে এই সমাধানটি এখনও বিদ্যমান; প্রতিবিম্বের দামের জন্য কারও শব্দ গ্রহণ করবেন না - এটি নিজের জন্য পরীক্ষা করে দেখুন এবং আপনি এটি সামর্থ্য করতে পারেন কিনা তা দেখুন
nik.shornikov

1
@ ব্লুরাজা-ড্যানিপ্লুঘুফুট হ্যাঁ, এটি। Theালাই ছাড়াই এটি কেবলমাত্র একটি গতিশীল প্রার্থনা হবে, আপনি ইন্টার্নালগুলিতে যাবেন সে ক্ষেত্রে এটি। আরও সুনির্দিষ্টভাবে, এটি সুস্পষ্টভাবে প্রয়োগ করা হয়েছে: github.com/mono/mono/blob/master/mcs/class/dlr/ রুনটাইম/…
ডাইকাম

28

একটি গুরুত্বপূর্ণ পার্থক্য এখানে করা প্রয়োজন।

এখানে বেশিরভাগ উত্তরই ExpandoObject এর সাথে সুনির্দিষ্ট যা প্রশ্নে উল্লেখ করা হয়েছে। তবে একটি সাধারণ ব্যবহার (এবং অনুসন্ধানের সময় এই প্রশ্নে অবতরণের কারণ) হ'ল এএসপি.নেট এমভিসি ভিউব্যাগটি ব্যবহার করার সময়। এটি ডাইনামিকবজেক্টের একটি কাস্টম বাস্তবায়ন / সাবক্লাস, যা আপনি কোনও নালীর জন্য যেকোন স্বেচ্ছাসেবী সম্পত্তির নাম চেক করলে কোনও ব্যতিক্রম ছুঁড়ে না ফেলে। মনে করুন আপনি কোনও সম্পত্তি যেমন ঘোষণা করতে পারেন:

@{
    ViewBag.EnableThinger = true;
}

তাহলে ধরুন আপনি এর মানটি পরীক্ষা করতে চেয়েছিলেন এবং এটি এমনকি সেট করা আছে কিনা - এটি বিদ্যমান কিনা। নিম্নলিখিতটি বৈধ, সংকলন করবে, কোনও ব্যতিক্রম ছোঁড়াবে না এবং আপনাকে সঠিক উত্তর দেয়:

if (ViewBag.EnableThinger != null && ViewBag.EnableThinger)
{
    // Do some stuff when EnableThinger is true
}

এখনই সক্ষমকরণ-টিজার ঘোষণা থেকে মুক্তি পান। একই কোড সংকলন করে সঠিকভাবে চলে। প্রতিবিম্বের দরকার নেই।

ভিউব্যাগ থেকে ভিন্ন, ExpandoObject নিক্ষেপ করবে যদি আপনি এমন কোনও সম্পত্তি নেই যা অস্তিত্বহীন রয়েছে on আপনার নিজের থেকে এমভিসি ভিউব্যাগের মৃদু কার্যকারিতাটি পেতেdynamic অবজেক্টগুলির , আপনাকে গতিশীল করার একটি প্রয়োগ ব্যবহার করতে হবে যা ছুঁড়ে না।

আপনি কেবল এমভিসি ভিউব্যাগে সঠিক প্রয়োগটি ব্যবহার করতে পারেন:

. . .
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;
}
. . .

https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/DynamicViewDataDictionary.cs

আপনি এটি এখানে এমভিসি ভিউতে এমভিসি ভিউপেজে বাঁধা দেখতে পাচ্ছেন:

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

অন্য কথায়, এটি সর্বদা কীগুলির মধ্যে মূল্য নির্বিশেষে সমস্ত কীগুলির জন্য একটি মান প্রদান করে - কিছুই না থাকায় এটি কেবল শূন্য হয়ে যায়। তবে, ভিভিডাটাডেটরিয়ায় এমভিসির মডেলটির সাথে আবদ্ধ হওয়ার বোঝা রয়েছে, সুতরাং এমভিসি ভিউগুলির বাইরে ব্যবহারের জন্য কেবল দৃষ্টিনন্দন অভিধানের অংশগুলি ছাঁটাই করা ভাল।

এখানে সমস্ত সাহস পোস্ট করার জন্য এটি বেশ দীর্ঘ - এর বেশিরভাগই কেবল আইডোরিয়াস বাস্তবায়ন করে - তবে এখানে একটি গতিশীল অবজেক্ট (শ্রেণি DDict ) রয়েছে যা তে ঘোষিত হয়নি এমন সম্পত্তিগুলির নাল চেকের জন্য নিক্ষেপ করে না:

https://github.com/b9chris/GracefulDynamicDictionary

আপনি শুধু NuGet এর মাধ্যমে আপনার প্রকল্প এটি যোগ করতে চান, তাহলে এটির নাম GracefulDynamicDictionary


আপনি কেন ডাইনামিকড অভিধানে ভোট দিয়েছেন কেননা এটি তখন প্রতিবিম্ব ব্যবহার করে না?
সফটলিয়ন

তবে আপনি এটিতে ভোট দিতে পারেন কারণ এটি একই সমাধান :)
সফটলিয়ন

3
এটি অবশ্যই একই সমাধান নয়।
ক্রিস মোসচিনি

"আপনার কোনও অনুরূপ সাবক্লাস তৈরি করতে হবে যা কোনও সম্পত্তি পাওয়া না গেলে নিক্ষেপ করবে না" " => এটা! ওহ না এটা না। আমার সমাধান আরও ভাল। এটি ছুড়ে ফেলে - কারণ আমরা এটি চাই এবং ট্রাইএক্সএক্স ব্যবহার করা থাকলে এটি ফেলে দেওয়াও যায় না;
সফটলিয়ন

1
এই, আমি এখানে এসেছি ঠিক কেন, কিছু কোড (ভিউব্যাগ) কেন ভঙ্গ হচ্ছে না তা বুঝতে পারি না। ধন্যবাদ.
অ্যাডাম টলি 21

11

আমি সম্প্রতি একটি খুব অনুরূপ প্রশ্নের উত্তর দিয়েছি: আমি কীভাবে গতিশীল অবজেক্টের সদস্যদের প্রতিফলিত করব?

সংক্ষেপে, ExpandoObject আপনি পেতে পারেন কেবল গতিশীল অবজেক্ট নয়। প্রতিবিম্ব স্ট্যাটিক প্রকারের জন্য (আইডিনামিকমেটাওজেক্টপ্রোভাইডার প্রয়োগ না করে এমন প্রকারের) জন্য কাজ করবে। এই ইন্টারফেসটি প্রয়োগ করে এমন ধরণের ক্ষেত্রে, প্রতিফলনটি মূলত অকেজো। ExpandoObject এর জন্য, আপনি কেবল অন্তর্নিহিত অভিধানে সম্পত্তিটি কী হিসাবে সংজ্ঞায়িত হয়েছে কিনা তা খতিয়ে দেখতে পারেন। অন্যান্য বাস্তবায়নের জন্য, এটি চ্যালেঞ্জ হতে পারে এবং কখনও কখনও ব্যতিক্রম ছাড়া কাজ করার একমাত্র উপায়। বিস্তারিত জানার জন্য উপরের লিঙ্কটি অনুসরণ করুন।


11

আপডেট করা: আপনি প্রতিনিধিদের ব্যবহার করতে পারেন এবং যদি এটি বিদ্যমান থাকে তবে গতিশীল অবজেক্টের সম্পত্তি থেকে একটি মান পাওয়ার চেষ্টা করতে পারেন। কোনও সম্পত্তি না থাকলে কেবল ব্যতিক্রমটি ধরুন এবং মিথ্যা প্রত্যাবর্তন করুন।

একবার দেখুন, এটি আমার পক্ষে ভাল কাজ করে:

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

2
@ মার্ক্লাম সমস্ত ব্যতিক্রম ধরা খারাপ, যখন আপনি জানেন না যে ব্যতিক্রমের কারণ কী। আমাদের ক্ষেত্রে এটি ঠিক আছে যেহেতু আমরা সম্ভবত কোনও ক্ষেত্রের অনুপস্থিতি আশা করি।
আলেকজান্ডার জি

3
যদি আপনি জানেন যে ব্যতিক্রমের কারণ কী তা অবশ্যই আপনার প্রকারটিও জেনে রাখা উচিত, সুতরাং ধরুন (যাই হোক না কেন) অন্যথায় আপনার কোডটি একটি অপ্রত্যাশিত ব্যতিক্রম পেয়ে গেলেও - নিঃশব্দে চালিয়ে যাবে - যেমন আউট অফ মেমরিএক্সসেপশন যেমন।
মার্কলাম

4
আপনি যে কোনও গেটে পাস করতে পারবেন IsPropertyExist। এই উদাহরণে, আপনি জানেন যে কেউ একটি নিক্ষেপ করতে পারে InvalidOperationException। অনুশীলনে, কোন ব্যতিক্রম নিক্ষেপ করা হতে পারে তা আপনার কোনও ধারণা নেই। কার্গো ধর্মের প্রতিবাদের জন্য +1
পাইদার

2
পারফরম্যান্স গুরুত্বপূর্ণ হলে এই সমাধানটি অগ্রহণযোগ্য, উদাহরণস্বরূপ যদি 500+ পুনরাবৃত্তির সাথে কোনও লুপে এটি ব্যবহৃত হয় এবং এটি অনেক সেকেন্ডের বিলম্বের কারণ হতে পারে। প্রতিবার একটি ব্যতিক্রম ধরা পড়লে স্ট্যাকটি অবশ্যই ব্যতিক্রম বস্তুতে অনুলিপি করা উচিত
Jim109

1
পুনরায়: পারফরম্যান্স: ডিবাগারটি সংযুক্ত হচ্ছে এবং কনসোল W রাইটলাইন হ'ল ধীর বিট। 10,000 টি পুনরাবৃত্তি এখানে 200 মিমি থেকেও কম সময় নেয় (পুনরাবৃত্তিতে 2 ব্যতিক্রম সহ)। কোনও ব্যতিক্রম ছাড়াই একই পরীক্ষাটি কয়েক মুঠো মিলিসেকেন্ড নেয় takes এর অর্থ যদি আপনি এই কোডটির ব্যবহারটি খুব কমই কোনও সম্পত্তি হারিয়ে যাচ্ছেন বা আপনি যদি এটিকে সীমিত সংখ্যক বার বলছেন বা ফলাফলগুলি ক্যাশে করতে পারেন তবে আপনি দয়া করে বুঝতে পারেন যে সমস্ত কিছুর নিজস্ব স্থান এবং অতিমাত্রায় কোনওটিই নেই এখানে নিয়মিত সতর্কতা গুরুত্বপূর্ণ matter
বিশৃঙ্খলা

10

আমি একটি এক্সটেনশন পদ্ধতি তৈরি করতে চেয়েছিলাম যাতে আমি এর মতো কিছু করতে পারি:

dynamic myDynamicObject;
myDynamicObject.propertyName = "value";

if (myDynamicObject.HasProperty("propertyName"))
{
    //...
}

... তবে আপনি ExpandoObjectসি # 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"))
{
    ...
}

4
ExpandoObject এর জন্য এক্সটেনশনে দরকারী মন্তব্য এবং লিঙ্কের পক্ষে ভোট দিন।
রবার্তো

1

আপনি টাইপ যথাযথ সেটগুলি পেতে প্রতিবিম্বটি কেন ব্যবহার করতে চান না? এটার মত

 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
 } 

আমি নিশ্চিত নই যে এটি গতিশীল যুক্ত হওয়া বৈশিষ্ট্যগুলি ফিরিয়ে দেবে কিনা, আমার ধারণা এটি ডায়নামিক অবজেক্টের পদ্ধতিগুলি ফিরিয়ে দেয়।
ডায়কাম

1

এই এক্সটেনশন পদ্ধতিটি কোনও সংস্থার অস্তিত্বের জন্য পরীক্ষা করে এবং তারপরে মান বা নাল ফেরায়। এটি যদি আপনার অ্যাপ্লিকেশনগুলি অপ্রয়োজনীয় ব্যতিক্রম ছুঁড়ে না দিতে চায় তবে এটি কার্যকর হয়, কমপক্ষে যা আপনি সহায়তা করতে পারেন।

    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");

1

আপনার ব্যবহারের ক্ষেত্রে, যদি শূন্যটিকে অপরিজ্ঞাত হিসাবে একই হিসাবে বিবেচনা করা যায় তবে আপনি আপনার ExpandoObjectটিকে ডায়নামিকজেসনঅজেক্টে রূপান্তর করতে পারেন।

    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


-3

আরে ছেলেরা প্রত্যেকটির প্রতিচ্ছবি ব্যবহার করা বন্ধ করে দেয় যার জন্য প্রচুর সিপিইউ চক্র ব্যয় হয়।

সমাধান এখানে:

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;
    }
}

4
এটি দেখায় যে কীভাবে ডায়নামিক অবজেক্টটি প্রয়োগ করা যায়, কীভাবে এটি দেখতে হয় না যে কোনও গতিশীল বস্তুতে কোনও সম্পত্তি কীভাবে প্রস্থান করে।
ম্যাট ওয়ারেন

প্রশ্নযুক্ত সম্পত্তিটির বিরুদ্ধে কোনও গতিশীল উদাহরণের নাল চেক করে আপনি পরীক্ষা করতে পারেন।
ctorx

2
"এটি দেখায় কীভাবে ডায়নামিক অবজেক্টটি প্রয়োগ করা যায়": হ্যাঁ বাস্তবে এটি। এই প্রশ্নের সমাধান হ'ল: জেনেরিক কোনও সমাধান নেই কারণ এটি বাস্তবায়নের উপর নির্ভর করে।
সফটলিয়ন

@Softlion না, সমাধান জিনিস আমরা যে আছে ব্যবহার বন্ধ
nik.shornikov

@ সফ্টলিয়ন ট্রাইএক্সএক্সএক্স পদ্ধতিগুলির মূল বিষয় কী? সম্পত্তি পাওয়া না গেলে ট্রাইগেট কখনই মিথ্যা ফিরবে না, সুতরাং ফলাফলটি আপনাকে এখনও পরীক্ষা করতে হবে। রিটার্ন অকেজো। ট্রাইসেটে, যদি কীটি বিদ্যমান না থাকে, তবে এটি মিথ্যা প্রত্যাবর্তনের পরিবর্তে একটি ব্যতিক্রম ছুঁড়ে দেবে। আপনি কেন এটিকে উত্তর হিসাবে ব্যবহার করবেন তা আমি বুঝতে পারি না, আপনি নিজেরাই এখানে মন্তব্যগুলিতে লিখলে "এই প্রশ্নের সমাধানটি হল: বাস্তবায়নের উপর নির্ভর করে কোনও জেনেরিক সমাধান নেই", এটিও সত্য নয়। আসল সমাধানের জন্য ডাইকমের উত্তর দেখুন।
pqsk

-5

আর একবার চেষ্টা কর

public bool PropertyExist(object obj, string propertyName)
{
 return obj.GetType().GetProperty(propertyName) != null;
}

3
এটি গতিশীল নামের অধীনে লুকানো অবজেক্টের কোনও সম্পত্তির অস্তিত্ব পরীক্ষা করতে পারে, যা একটি বাস্তবায়ন বিশদ। আপনি কি পোস্ট করার আগে রিয়েল কোডে আপনার সমাধানটি যাচাই করেছেন? এটি কিছুতেই কাজ করা উচিত নয়।
সফটলিয়ন

আমি কোডটির এই অংশটি রিয়েল টাইম দৃশ্যে ব্যবহার করেছি। এটি ভাল কাজ করে।
ভেঙ্কট

6
সম্পত্তি থাকা সত্ত্বেও আমাকে সর্বদা শূন্য করে।
আটলান্টিস

এটি বেসিক অবজেক্টের সাথে কাজ করবে তবে এক্সপেন্ডোঅবজেক্টসের সাথে নয়। গতিশীল, নিশ্চিত নয় not
জো

1
নিশ্চিত করার জন্য, এটি কোনওdynamic বস্তুর সাথে কাজ করে না (সর্বদা ফিরে আসে null)।
কোডিং হয়েছে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.