سؤال

ما هي الاختلافات بين System.Dynamic.ExpandoObject, System.Dynamic.DynamicObject و dynamic?

في أي مواقف تستخدم هذه الأنواع؟

هل كانت مفيدة؟

المحلول

ال dynamic يتم استخدام الكلمة الرئيسية لإعلان المتغيرات التي يجب أن تكون متأخرة.
إذا كنت ترغب في استخدام الربط المتأخر ، لأي نوع حقيقي أو متخيل ، يمكنك استخدام dynamic الكلمة الرئيسية والمترجم يفعل الباقي.

عندما تستخدم dynamic الكلمة الرئيسية للتفاعل مع مثيل عادي ، DLR يقوم بإجراء مكالمات متأخرة إلى الأساليب العادية للمثال.

ال IDynamicMetaObjectProvider واجهه المستخدم يسمح للفصل بالسيطرة على سلوكه المتأخر.
عندما تستخدم dynamic الكلمة الرئيسية للتفاعل مع IDynamicMetaObjectProvider التنفيذ ، يدعو DLR IDynamicMetaObjectProvider الأساليب والكائن نفسه يقرر ما يجب القيام به.

ال ExpandoObject و DynamicObject الفصول هي تطبيقات IDynamicMetaObjectProvider.

ExpandoObject هو فئة بسيطة تتيح لك إضافة أعضاء إلى مثيل واستخدامها dynamicحليف.
DynamicObject هو تطبيق أكثر تقدماً يمكن أن يكون موروثة لتوفير سلوك مخصص بسهولة.

نصائح أخرى

سأحاول تقديم إجابة أوضح لهذا السؤال ، لشرح بوضوح الاختلافات بين الديناميكية ، ExpandoObject و DynamicObject.

سريع جدا، dynamic هي كلمة رئيسية. إنه ليس نوعًا لكل س. إنها كلمة رئيسية تخبر المترجم بتجاهل فحص النوع الثابت في وقت التصميم وبدلاً من ذلك لاستخدام الربط المتأخر في وقت التشغيل. لذلك لن نقضي الكثير من الوقت dynamic في بقية هذه الإجابة.

ExpandoObject و DynamicObject هي في الواقع أنواع. على السطح ، تبدو مشابهة جدًا لبعضها البعض. كلا الفئتين تنفيذ IDynamicMetaObjectProvider. ومع ذلك ، حفر أعمق وستجد أنها ليست متشابهة على الإطلاق.

DynamicObject هو تنفيذ جزئي ل IDynamicMetaObjectProvider من المفترض أن تكون نقطة انطلاق للمطورين لتنفيذ أنواعهم المخصصة التي تدعم الإرسال الديناميكي مع سلوك التخزين والاسترجاع الأساسي المخصص لجعل أعمال الإرسال الديناميكية.

  1. لا يمكن بناء DynamicObject مباشرة.
  2. يجب عليك تمديد DynamicObject لكي يكون لديك أي استخدام لك كمطور.
  3. عندما تقوم بتمديد DynamicObject ، يمكنك الآن توفير سلوك مخصص فيما يتعلق بكيفية رغبة في حل Dynamic Dispatch إلى البيانات المخزنة داخليًا في تمثيل البيانات الأساسي في وقت التشغيل.
  4. تقوم ExployObject بتخزين البيانات الأساسية في القاموس ، وما إلى ذلك. إذا قمت بتطبيق DynamicObject ، فيمكنك تخزين البيانات أينما تريد. (على سبيل المثال ، فإن كيفية الحصول على البيانات الخاصة بك وتعيينها على الإرسال متروك لك تمامًا).

باختصار ، استخدم DynamicObject عندما تريد إنشاء أنواعك الخاصة التي يمكن استخدامها مع DLR والعمل مع أي سلوكيات مخصصة تريدها.

مثال: تخيل أنك ترغب في الحصول على نوع ديناميكي يعيد افتراضيًا مخصصًا كلما تمت محاولة الحصول على عضو غير موجود (أي لم تتم إضافته في وقت التشغيل). وسيقول هذا الافتراضي ، "أنا آسف ، لا توجد ملفات تعريف الارتباط في هذه الجرة!". إذا كنت تريد كائنًا ديناميكيًا يتصرف مثل هذا ، فستحتاج إلى التحكم في ما يحدث عند عدم العثور على حقل. لن يسمح لك ExplostObject بذلك. لذلك ستحتاج إلى إنشاء نوع خاص بك مع سلوك دقة (إرسال) ديناميكية فريدة من نوع ExpandoObject.

يمكنك إنشاء نوع على النحو التالي: (ملاحظة ، الرمز أدناه مخصص فقط للتوضيح وقد لا يتم تشغيله. للتعرف على كيفية استخدام DynamicObject بشكل صحيح ، هناك العديد من المقالات والدروس التعليمية في أماكن أخرى.)

public class MyNoCookiesInTheJarDynamicObject : DynamicObject
{
    Dictionary<string, object> properties = new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        if (properties.ContainsKey(binder.Name))
        {
            result = properties[binder.Name];
            return true;
        }
        else
        {
            result = "I'm sorry, there are no cookies in this jar!"; //<-- THIS IS OUR 
            CUSTOM "NO COOKIES IN THE JAR" RESPONSE FROM OUR DYNAMIC TYPE WHEN AN UNKNOWN FIELD IS ACCESSED
            return false;
        }
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        properties[binder.Name] = value;
        return true;
    }

    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        dynamic method = properties[binder.Name];
        result = method(args[0].ToString(), args[1].ToString());
        return true;
    }
}

الآن ، يمكننا استخدام هذه الفئة الخيالية التي أنشأتها للتو كنوع ديناميكي له سلوك مخصص للغاية إذا لم يكن الحقل موجودًا.

dynamic d = new MyNoCookiesInTheJarDynamicObject();
var s = d.FieldThatDoesntExist;

//in our contrived example, the below should evaluate to true
Assert.IsTrue(s == "I'm sorry, there are no cookies in this jar!")

ExpandoObject هو تنفيذ كامل ل IDynamicMetaObjectProvider, ، حيث اتخذ فريق .NET Framework كل هذه القرارات لك. هذا مفيد إذا لم تكن بحاجة إلى أي سلوك مخصص ، وتشعر أن ExployObject يعمل بشكل جيد بما يكفي لك (90 ٪ من الوقت ، ExpandoObject هو جيد بما فيه الكفاية). على سبيل المثال ، راجع ما يلي ، وذلك بالنسبة إلى ExployOoBject ، اختار المصممون إلقاء استثناء إذا لم يكن العضو الديناميكي موجودًا.

dynamic d = new ExpandoObject();

/*
The ExpandoObject designers chose that this operation should result in an 
Exception. They did not have to make that choice, null could 
have been returned, for example; or the designers could've returned a "sorry no cookies in the jar" response like in our custom class. However, if you choose to use 
ExpandoObject, you have chosen to go with their particular implementation 
of DynamicObject behavior.
*/

try {
var s = d.FieldThatDoesntExist;
}
catch(RuntimeBinderException) { ... }

لتلخيص ، ExpandoObject هي ببساطة طريقة واحدة تم اختيارها مسبقًا لتمديد DynamicObject مع بعض السلوكيات الديناميكية التي من المحتمل أن تعمل من أجلك, ، ولكن قد لا يعتمد على احتياجاتك الخاصة.

بينما، DyanmicObject هو نموذج مساعد يجعل تنفيذ الأنواع الخاصة بك مع سلوكيات ديناميكية فريدة بسيطة وسهلة.

برنامج تعليمي مفيد يستند إليه الكثير من المصدر المذكور أعلاه.

وفقًا لمواصفات لغة C# dynamic هو إعلان نوع. بمعنى آخر dynamic x يعني المتغير x لديه النوع dynamic.

DynamicObject هو نوع يجعل من السهل تنفيذها IDynamicMetaObjectProvider وبالتالي تجاوز سلوك الربط المحدد للنوع.

ExpandoObject هو نوع يعمل مثل حقيبة الممتلكات. أي يمكنك إضافة خصائص وطرق وما إلى ذلك إلى مثيلات ديناميكية من هذا النوع في وقت التشغيل.

المثال أعلاه من DynamicObject لا يخبر الفرق بوضوح ، لأنه ينفذ بشكل أساسي الوظيفة التي يتم توفيرها بالفعل بواسطة ExpandoObject.

في الرابطين المذكورة أدناه ، من الواضح جدًا ذلك بمساعدة DynamicObject, ، من الممكن الحفاظ على/تغيير النوع الفعلي (XElement في المثال المستخدم في الروابط أدناه) وتحكم أفضل على الخصائص والأساليب.

https://blogs.msdn.microsoft.com/csharpfaq/2009/09/30/dynamic-in-c-4-0-introducing-the-expandoObject/

https://blogs.msdn.microsoft.com/csharpfaq/2009/10/19/dynamic-in-c-4-0-creating-wrappers-with-dynamicobject/

public class DynamicXMLNode : DynamicObject    
{    
    XElement node;

    public DynamicXMLNode(XElement node)    
    {    
        this.node = node;    
    }

    public DynamicXMLNode()    
    {    
    }

    public DynamicXMLNode(String name)    
    {    
        node = new XElement(name);    
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)    
    {    
        XElement setNode = node.Element(binder.Name);

        if (setNode != null)    
            setNode.SetValue(value);    
        else    
        {    
            if (value.GetType() == typeof(DynamicXMLNode))    
                node.Add(new XElement(binder.Name));    
            else    
                node.Add(new XElement(binder.Name, value));    
        }

        return true;    
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)    
    {    
        XElement getNode = node.Element(binder.Name);

        if (getNode != null)    
        {    
            result = new DynamicXMLNode(getNode);    
            return true;    
        }    
        else    
        {    
            result = null;    
            return false;    
        }    
    }    
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top