Различия между ExpandoObject, DynamicObject и dynamic



В чем разница между System.Dynamic.ExpandoObject,System.Dynamic.DynamicObject и dynamic?



В каких ситуациях вы используете эти типы?

662   4  

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 чисто предназначенный для того, чтобы быть отправной точкой для разработчиков, чтобы реализовать свои собственные пользовательские типы, поддерживающие динамическую отправку с пользовательским базовым поведением хранения и извлечения, чтобы сделать работу динамической отправки.

  1. DynamicObject не может быть построены непосредственно.
  2. вы должны расширить DynamicObject, чтобы он имел какое-либо использование для вас в качестве разработчика.
  3. когда вы расширяете DynamicObject, теперь вы можете предоставить пользовательское поведение относительно того, как вы хотите, чтобы динамическая отправка разрешала данные, хранящиеся внутри вашего базового представления данных во время выполнения.
  4. магазинах 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 в Примере, используемом в приведенных ниже ссылках) и лучший контроль над свойствами и методы.

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;

        }

    }

}

Comments

    Ничего не найдено.