Различия между расширенным допуском, динамическими продуктами и динамическими
-
01-10-2019 - |
Вопрос
Каковы различия между System.Dynamic.ExpandoObject
, System.Dynamic.DynamicObject
а также dynamic
?
В каких ситуациях вы используете эти типы?
Решение
То dynamic
Ключевое слово используется для объявления переменных, которые должны быть поздно.
Если вы хотите использовать поздние привязки, для любого реального или воображаемого типа вы используете dynamic
Ключевое слово и компилятор делает остальные.
Когда вы используете dynamic
Ключевое слово для взаимодействия с нормальным экземпляром, Длр Выполняет поздние призывы к нормальным методам экземпляра.
То IDynamicMetaObjectProvider
интерфейс Позволяет классу контролировать свое поздние поведение.
Когда вы используете dynamic
ключевое слово для взаимодействия с IDynamicMetaObjectProvider
Реализация, DLR вызывает IDynamicMetaObjectProvider
Методы и сам объект решает, что делать.
То ExpandoObject
а также DynamicObject
Классы - это реализации IDynamicMetaObjectProvider
.
ExpandoObject
это простой класс, который позволяет добавлять членов в экземпляр и использовать их dynamic
союзник.
DynamicObject
является более продвинутой реализацией, которая может быть унаследована, чтобы легко обеспечить индивидуальное поведение.
Другие советы
Я постараюсь предоставить более четкий ответ на этот вопрос, четко объяснить, какие различия между динамическими, ExpandoObject
а также DynamicObject
.
Очень быстро, dynamic
это ключевое слово. Это не тип se-se. Это ключевое слово, которое позволяет компилятору игнорировать статический тип проверки в режиме проектирования и вместо этого использовать поздние привязки во время выполнения. Так что мы не будем тратить много времени на dynamic
В остальном этот ответ.
ExpandoObject
а также DynamicObject
действительно типы. На поверхности они выглядят очень похожи друг на друга. Оба класса реализуются IDynamicMetaObjectProvider
. Отказ Тем не менее, копайте глубже, и вы найдете, что они совсем не похожи.
DynamicObject - это частичная реализация IDynamicMetaObjectProvider
Чисто предназначался, чтобы быть отправной точкой для разработчиков для реализации своих собственных пользовательских типов, поддерживающих динамическую динамическую рассылку с пользовательским поведением базового хранения и поиска для создания динамической диспетчерской работы.
- DynamicObject не может быть сконструирован напрямую.
- Вы должны продлить динамическое значение для него, чтобы иметь для вас любое использование в качестве разработчика.
- Когда вы продвигаете DynamicObject, вы теперь можете предоставить пользовательское поведение в отношении того, как вы хотите, чтобы динамическая отправка разрешила в данные, сохраненные внутри, в вашем базовом представлении данных во время выполнения.
- Расширенные хранилищ основных данных в словаре и т. Д. Если вы реализуете DynamicObject, вы можете хранить данные везде, где и даже хотите. (например, как вы получаете и устанавливаете данные о диспетчере, полностью зависит от вас).
Короче говоря, используйте DynamicObject, если вы хотите создать свои собственные типы, которые можно использовать с DLR и работать с любым пользовательским поведением, которое вы хотели бы.
Пример: представьте, что вы хотите иметь динамический тип, который возвращает пользовательский по умолчанию всякий раз, когда получение предпринимается на участнике, который не существует (т.е. не был добавлен во время выполнения). И что по умолчанию скажет: «Извините, в этой банке нет файлов!». Если вы хотите динамический объект, который ведет себя так, вам нужно будет контролировать, что происходит, когда поле не найдено. Развертывать не позволит вам сделать это. Таким образом, вам нужно создать свой собственный тип с уникальным поведением динамического разрешения элементов (отправка) и использовать, а не готовый 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 Team сделала все эти решения для вас. Это полезно, если вам не нужно какое-либо поведение, и вы чувствуете, что развертывание работает достаточно хорошо для вас (90% времени, 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
просто один заранее выбранный способ расширить динамику Veach с определенным динамическим динамическим поведением, которые, вероятно, будут работать для вас, но не может в зависимости от ваших особых потребностей.
В то время как, DyanmicObject
Это помощник BaseType, который делает реализацию ваших собственных типов с уникальным динамическим поведением простым и легким.
Полезный урок, на котором основан большая часть примера источника выше.
Согласно спецификации языка 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-te-expandoobject/
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;
}
}
}