ExpandoObject, DynamicObject ve dynamic arasındaki farklar


170

Arasındaki farklar nelerdir System.Dynamic.ExpandoObject,System.Dynamic.DynamicObject ve dynamic?

Hangi durumlarda bu türleri kullanıyorsunuz?

Yanıtlar:


154

dynamicAnahtar kelime sonradan bağlanan edilmelidir değişkenleri bildirmek için kullanılır.
Geç bağlama kullanmak istiyorsanız, herhangi bir gerçek veya hayal edilen tür için, dynamicanahtar kelimeyi kullanırsınız ve derleyici gerisini halleder.

dynamicAnahtar kelimeyi normal bir örnekle etkileşim kurmak için kullandığınızda, DLR örneğin normal yöntemlerine geç bağlı çağrılar gerçekleştirir.

IDynamicMetaObjectProviderArayüz sınıf onun sonradan bağlanan davranışın kontrol altına almak için izin verir.
Eğer kullandığınız zaman dynamicbir etkileşim için anahtar kelime IDynamicMetaObjectProvideruygulanması, DLR çağırır IDynamicMetaObjectProvideryöntem ve nesnenin kendisi ne yapacağını karar verir.

ExpandoObjectVe DynamicObjectsınıfları uygulamaları vardır IDynamicMetaObjectProvider.

ExpandoObjectbir örneğe üye eklemenizi ve bunları dynamicmüttefik olarak kullanmanızı sağlayan basit bir sınıftır .
DynamicObjectkolayca özelleştirilmiş davranış sağlamak için miras alınabilen daha gelişmiş bir uygulamadır.


2
Bununla ilgili daha fazla bilgi edinmek için iyi bir yer ne olabilir? API değil, API'nin arkasındaki neden? Örneğin ExpandoObject neden ruby'nin 'method_missing' tabanlı programlaması için defacto taban tipine benzeyen DynamicObject'ten türemiştir.
Gishu

4
Mümkün olan yerlerde bazı kullanım örnekleri ekleyebilir misiniz? Örneğin, bir DynamicObject'i nasıl kullanırım ve faydaları nelerdir?
o

10
Bunun gibi örnekleri olmayan harika cevaplar, üstte kremasız kek gibidir.
Teoman shipahi


68

Bu soruya daha net bir cevap vermeye çalışacağım, dinamik ExpandoObjectve arasındaki farkların ne olduğunu net bir şekilde açıklayacağım DynamicObject.

Çok çabuk dynamicbir anahtar kelime. Kendi başına bir tür değildir. Derleyiciye tasarım zamanında statik tür denetlemesini yoksaymasını ve bunun yerine çalışma zamanında geç bağlama kullanmasını söyleyen bir anahtar sözcüktür. Yani dynamicbu cevabın geri kalanında fazla zaman geçirmeyeceğiz .

ExpandoObjectve DynamicObjectgerçekten türler. YÜZEYDE birbirlerine çok benziyorlar. Her iki sınıf da uygulanmaktadır IDynamicMetaObjectProvider. Ancak, daha derine inin ve onların birbirine benzemediğini göreceksiniz.

DynamicObject, IDynamicMetaObjectProvidergeliştiricilerin dinamik dağıtım çalışmasını sağlamak için özel temel depolama ve alma davranışıyla dinamik dağıtımı destekleyen kendi özel türlerini uygulamalarına yönelik bir başlangıç ​​noktası olması amaçlanan kısmi bir uygulamadır .

  1. DynamicObject doğrudan oluşturulamaz.
  2. DynamicObject'i geliştirici olarak kullanmanız için genişletmeniz GEREKİR.
  3. DynamicObject'i genişlettiğinizde, dinamik dağıtımın çalışma zamanında temel veri sunumunuzda dahili olarak depolanan verilere nasıl çözümlenmesini istediğinize ilişkin ÖZEL davranış sağlayabilirsiniz.
  4. ExpandoObject temel alınan verileri bir Sözlükte vb. Saklar. DynamicObject uygularsanız, verileri istediğiniz yerde ve istediğiniz şekilde saklayabilirsiniz. (örneğin, gönderimdeki verileri nasıl alıp ayarlayacağınız tamamen size bağlıdır).

Kısacası, DLR ile kullanılabilecek KENDİ türlerinizi oluşturmak istediğinizde DynamicObject kullanın ve istediğiniz ÖZEL davranışlarla çalışın.

Örnek: Mevcut OLMAYAN bir üyeye (örneğin çalışma zamanında eklenmemiş) bir üye girişimi denendiğinde, özel bir varsayılan değer döndüren dinamik bir türe sahip olmak istediğinizi düşünün. Ve bu varsayılan, "Üzgünüm, bu kavanozda çerez yok!" Böyle davranan dinamik bir nesne istiyorsanız, bir alan bulunamadığında ne olacağını kontrol etmeniz gerekir. ExpandoObject bunu yapmanıza izin vermeyecektir. Bu nedenle, benzersiz dinamik üye çözünürlüğü (dağıtım) davranışı ile kendi türünüzü oluşturmanız ve hazır yerleşik yerine bunu kullanmanız gerekir.ExpandoObject .

Aşağıdaki gibi bir tür oluşturabilirsiniz: (Not, aşağıdaki kod sadece örnekleme amaçlıdır ve çalışmayabilir. DynamicObject'in nasıl düzgün kullanılacağını öğrenmek için başka yerlerde birçok makale ve öğretici vardır.)

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;
    }
}

Şimdi, yeni oluşturduğumuz bu hayali sınıfı, alan yoksa çok özel bir davranışa sahip dinamik bir tür olarak kullanabiliriz.

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!")

ExpandoObjectIDynamicMetaObjectProvider.NET Framework ekibinin tüm bu kararları sizin için verdiği FULL uygulamasıdır . Herhangi bir özel davranışa ihtiyacınız yoksa ve ExpandoObject'in sizin için yeterince iyi çalıştığını düşünüyorsanız (zamanın% 90'ı ExpandoObjectyeterince iyi). Örneğin, aşağıdakilere bakın ve ExpandoObject için tasarımcılar dinamik üye yoksa bir istisna atmayı seçti.

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) { ... }

Özetlemek gerekirse, ExpandoObjectDynamicObject'i muhtemelen sizin için çalışacak , ancak özel ihtiyaçlarınıza bağlı olmayabilecek belirli dinamik gönderme davranışlarıyla genişletmek için önceden seçilmiş bir yoldur .

Oysa, DyanmicObjectbenzersiz dinamik davranışlarla kendi türlerinizi uygulamayı basit ve kolay hale getiren bir yardımcı BaseType.

Yukarıdaki örnek kaynağın çoğunun dayandığı yararlı bir öğretici.


Çok iyi bir açıklama. Tek bir teknik düzeltme: ExpandoObject, DynamicObject'ten miras kalmaz.
Mike Rosoft

Şu örnek için küçük bir düzeltme DynamicObject: geçersiz kılma sırasında TryGetMember, false değerini döndürürseniz RuntimeBinderException, var olmayan bir mülke erişmeye çalışırken a atılır. Snippet'in gerçekten çalışması için geri dönmelisiniz true.
lluchmk

36

C # dil özelliklerine dynamicgöre bir tür bildirimi. Yani dynamic xdeğişkenin xtürü vardır dynamic.

DynamicObject, tür IDynamicMetaObjectProvideriçin belirli bağlama davranışının uygulanmasını ve bu nedenle geçersiz kılmayı kolaylaştıran bir türdür.

ExpandoObjectbir mülkiyet çantası gibi davranan bir tiptir. Yani çalışma zamanında bu tür dinamik örneklere özellikler, yöntemler vb. Ekleyebilirsiniz.


25
dynamicgerçek bir tür değildir ... derleyiciye bu değişken için geç bağlamayı kullanmasını söylemek sadece bir ipucudur. dynamicdeğişkenleri objectMSIL'de olduğu gibi bildirildi
Thomas Levesque

1
@Thomas: derleyicinin bakış açısından bir tür, ancak çalışma zamanı gösteriminin Object nesnesidir. Birkaç MS sunumunda "statik olarak dinamik olarak yazılmıştır" ifadesini bulacaksınız.
Brian Rasmussen

3
@Thomas: ve spec özelliği "C # 4.0, dinamik adı verilen yeni bir statik tür sunuyor" diyor.
Brian Rasmussen

Gerçekten ... Ama bence bunu bir tür olarak düşünmek kafa karıştırıcı, çünkü DynamicObject veya ExpandoObject gibi türlerle kalıtım ilişkisi yok
Thomas Levesque

3
Ben burada seninleyim. Ancak, dil belirtimi ona bir tür diyor, bu yüzden devam ediyorum.
Brian Rasmussen

0

Yukarıdaki örnek DynamicObject, farkı net bir şekilde anlatmaz, çünkü temel olarak zaten sağlanan işlevselliği uygular.ExpandoObject .

Aşağıda belirtilen iki bağlantıda DynamicObject, gerçek türün ( XElementaşağıdaki bağlantılarda kullanılan örnekte) korunmasının / değiştirilmesinin ve özellikler ve yöntemler üzerinde daha iyi kontrolün mümkün olduğu çok açıktır .

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;    
        }    
    }    
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.