2009-06-07 15 views
6

dynamic yöntem çağrılarını (özellikle RuntimeBinderException s yükseltecek olanlar) RealProxy ile kesişmenin bir yolu var mı? Bunun istisnasını yakalamayı ve bunun üzerinde 'metodun eksikliğini' uyguladığımı umuyordum, ama ara vericiye bakmadan önce atılmış gibi görünüyor.C# 4.0'deki eksik yöntem eksiklikleri: dinamik vs RealProxy

Testim sadece benziyor:

World aslında DynamicObject üzerinde uygulanmadı
dynamic hello = MethodMissingInterceptor<DynamicObject>.Create(); 
Assert.AreEqual("World", hello.World()); 

. önleme oldukça basittir - Ben RuntimeBinderException için IMethodReturnMessage.Exception kontrol ve benzeri bir şey üzerine iletmek için umuyordum:

public IMessage MethodMissing(IMethodCallMessage call) 
{ 
    return new ReturnMessage(call.MethodBase.Name, new object[0], 0, call.LogicalCallContext, call); 
} 

Ne yazık ki, benim yakalayıcısı bakın hepsi bir GetType yapılan çağrılar değil, var olmayan World yöntemdir .

Başarısızlık - .NET 4.0'da mutlu çalışan bir DynamicProxy sürümü olup olmadığını henüz bilmiyor, ancak bu sorunla uğraşmış olabilir mi?

cevap

17

Uzun yanıtla başlayacağım. C# dinamik operasyon Her bağlama bu sırada yaklaşık bu üç şey yapar:

  1. o IDynamicMetaObjectProvider uygular veya bir COM nesnesi ise kendisini bağlamak için nesneyi sorun ve o, o zaman ...
  2. başarısız olursa
  3. Yansıma kullanarak bir düz eski clr-nesnesindeki bir işlemin çalışmasına bağlanın ve bu başarısız olursa, o zaman ...
  4. Bağlama için tam bir başarısızlığı temsil eden bir DynamicMetaObject döndürün. 2. adımda, C# çalışma zamanı bağlayıcı aramak uygun bir "Dünya" yöntemine sahip olmadığını anlamaya denemek için üzerinizde yansıtan alındığı için GetType görüyoruz

çağırır ve bunun nedeni oluyor Eğer bir tane varsa, mertebenin IDynamicMetaObjectProvider uygulaması, yapılacak özel bir şey ile gelemedi.

Ne yazık ki sizin için RuntimeBinderException atıldığı zaman, artık bağlayıcı değiliz. İstisna, 3. adımdan kaynaklanan geri döndürülen meta nesnesine yanıt olarak, dinamik işlemin yürütme aşamasından çıkar. Bunu yakalamanız için tek fırsat gerçek çağrı sitesinde.

Bu yöntem C# içinde method_missing uygulamak istiyorsanız, bu strateji sizin için işe yaramayacaktır. Gerçi bazı seçenekleriniz var.

Kolay bir seçenek, MethodMissingInterceptor'unuza IDynamicMetaObjectProvider uygulamak ve sarılmış nesnenin IDMOP uygulamasına geçmektir. İç IDMOP kısmında arıza olması durumunda, ne istersen ona bağlanabilirsiniz (belki de interceptorda saklanan bir metodun gönderilmesi için bir yöntem çağrısı). Bunun dezavantajı, sadece dinamik nesneler olduğu bilinen nesneler için çalışmaktadır, örn. başlamak için IDMOP uygulayanlar. Bunun nedeni, temel olarak 1. ve 2. adımlar arasına kendinizi yerleştirmenizdir. Bunun için düşünebildiğim başka bir alternatif de, IDynamicMetaObjectProvider'ı uygulamaktır ve içinde her bağlamaya olumlu yanıt vermek, bir çağrıyı (a) üreten bir yönteme döndürmektir. C# derleyicisi aynı kodu ilk etapta bağlamak için üretilmiş olurdu ve (b) bir method_missing yöntemi çağırmak için RuntimeBinderException yakalar.Bunun dezavantajı, oldukça karmaşık olacağıdır - keyfi olarak kullanılan temsilci türleri ve bunları kullanan IL'yi, kamusal tüketim için açık olmayan C# çalışma zamanı ciltleme derlemesindeki genel türlere karşı oluşturmanız gerekir. Ama en azından tüm operasyonlara karşı eksik metodlar alacaksın.

Uzaklaştırma proxy'lerini kullanma konusunda ipucu vermiş gibi düşündüğüm başka stratejiler olduğundan eminim. Yine de neye benzediklerini hayal edemiyorum ve başarılı olup olmadıklarını söyleyemem.

Buradaki problemin özü, C# 4.0'un bunu yapma isteğinizi öngören bir tasarıma sahip olmamasıdır. Özellikle, 2 ve 3 adımları arasında kendinizi kolayca ekleyemezsiniz. Bu da beni kısa cevabı getiriyor, bu da üzgün olan C# 4.0 metod_missing'e sahip değil.

+0

Kusursuz bir açıklama için teşekkürler, Chris - Blogunuzda C# 'dinamik' yazı dizilerinden devam etmeye başladım. :) Amaçlarım için, ilk çözümünüz işe yarayacakmış gibi geliyor. Bu çağrıları yalnızca yapımcı nesneler için yapmak ve API'ları test etme konusunda bazı akıcılık kazandırmak istiyorum, bunları keyfi nesnelerde yakalamam gerekmez. – Thom

+0

@Chris - "sadece durumda" nın yukarıdaki soruya da dikkat edin; Aslında bunu bilmek isterim; -p –

+0

Dinamik nesneyi, bir üyenin varlığını gerçekten aramadan sorgulamak için bir yolu var mı? –