الاختلافات بين التوسيع والديناميكي والديناميكي
-
01-10-2019 - |
سؤال
ما هي الاختلافات بين 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
من المفترض أن تكون نقطة انطلاق للمطورين لتنفيذ أنواعهم المخصصة التي تدعم الإرسال الديناميكي مع سلوك التخزين والاسترجاع الأساسي المخصص لجعل أعمال الإرسال الديناميكية.
- لا يمكن بناء DynamicObject مباشرة.
- يجب عليك تمديد DynamicObject لكي يكون لديك أي استخدام لك كمطور.
- عندما تقوم بتمديد DynamicObject ، يمكنك الآن توفير سلوك مخصص فيما يتعلق بكيفية رغبة في حل Dynamic Dispatch إلى البيانات المخزنة داخليًا في تمثيل البيانات الأساسي في وقت التشغيل.
- تقوم 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
في المثال المستخدم في الروابط أدناه) وتحكم أفضل على الخصائص والأساليب.
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;
}
}
}