4 ответов:
The
dynamicключевое слово используется для объявления переменных, которые должны быть поздним связыванием.
Если вы хотите использовать позднюю привязку для любого реального или воображаемого типа, вы используетеdynamicключевое слово и компилятор делает все остальное.при использовании
dynamicключевое слово для взаимодействия с обычным экземпляром, DLR выполняет вызовы с поздней привязкой к обычным методам экземпляра.The
IDynamicMetaObjectProviderинтерфейс позволяет классу взять под свой контроль его поздним связыванием поведения.
Когда вы используетеdynamicключевое слово для взаимодействия сIDynamicMetaObjectProviderреализация, DLR вызываетIDynamicMetaObjectProviderметоды и сам объект решает, что делать.The
ExpandoObjectиDynamicObjectклассы являются реализациямиIDynamicMetaObjectProvider.
ExpandoObject- это простой класс, который позволяет добавлять участников в экземпляр и использовать ихdynamicсоюзник.DynamicObjectэто более продвинутая реализация, которая может быть унаследована, чтобы легко обеспечить индивидуальные поведение.
согласно спецификации языка C#
dynamic- это объявление типа. То естьdynamic xозначает, что переменнаяxтипdynamic.
DynamicObject- это тип, который позволяет легко реализоватьIDynamicMetaObjectProviderи, таким образом, переопределить поведение конкретной привязки к типу.
ExpandoObjectэто тип, который действует как мешок свойств. Т. е. вы можете добавлять свойства, методы и т. д. для динамических экземпляров этого типа во время выполнения.
я постараюсь дать более четкий ответ на этот вопрос, чтобы четко объяснить, в чем разница между динамическими,
ExpandoObjectиDynamicObject.очень быстро,
dynamic- ключевое слово. Это не тип как таковой. Это ключевое слово, которое говорит компилятору игнорировать статическую проверку типов во время разработки и вместо этого использовать позднюю привязку во время выполнения. Поэтому мы не собираемся тратить много времени наdynamicв остальной части этот ответ.
ExpandoObjectиDynamicObjectдействительно типы. На первый взгляд они очень похожи друг на друга. Оба класса реализуютIDynamicMetaObjectProvider. Однако копайте глубже, и вы обнаружите, что они совсем не похожи.DynamicObject является частичной реализацией
IDynamicMetaObjectProviderчисто предназначенный для того, чтобы быть отправной точкой для разработчиков, чтобы реализовать свои собственные пользовательские типы, поддерживающие динамическую отправку с пользовательским базовым поведением хранения и извлечения, чтобы сделать работу динамической отправки.
- DynamicObject не может быть построены непосредственно.
- вы должны расширить DynamicObject, чтобы он имел какое-либо использование для вас в качестве разработчика.
- когда вы расширяете DynamicObject, теперь вы можете предоставить пользовательское поведение относительно того, как вы хотите, чтобы динамическая отправка разрешала данные, хранящиеся внутри вашего базового представления данных во время выполнения.
- магазинах ExpandoObject базовые данные в словаре, и т. д. Если вы реализуете DynamicObject, вы можете хранить данные где угодно и как угодно как. (например, как вы получаете и устанавливаете данные по отправке полностью зависит от вас).
короче говоря, используйте DynamicObject, когда вы хотите создать свои собственные типы, которые можно использовать с DLR и работать с любыми пользовательскими поведениями, которые вы хотите.
пример: Представьте, что вы хотите иметь динамический тип, который возвращает пользовательское значение по умолчанию при попытке get для несуществующего элемента (т. е. не был добавлен во время выполнения). И этот дефолт скажет: "мне жаль, в этой банке нет печенья!". Если вам нужен динамический объект, который ведет себя так, вам нужно будет контролировать, что происходит, когда поле не найдено. ExpandoObject не позволит вам сделать это. Таким образом, вам нужно будет создать свой собственный тип с уникальным динамическим разрешением членов (dispatch) и использовать его вместо готового
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 приняла все эти решения за вас. Это полезно, если вам не нужно никакого пользовательского поведения, и вы чувствуете, что ExpandoObject работает достаточно хорошо для вас (90% время,ExpandoObject- Это достаточно хорошо). Так, например, см. Следующее, и что для ExpandoObject конструкторы решили создать исключение, если динамический элемент не существует.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является вспомогательным базовым типом, который делает реализацию собственных типов с уникальным динамическим поведением простым и легким.полезный учебник, на котором основана большая часть примера источника выше.
пример
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; } } }
Comments