2012-12-05 23 views
18

C# 'daki herhangi bir nesnede "sınıf düzeyinde üye" anlamında değil, "statik olarak tanımlanmış" anlamında statik olarak tanımlanmış (statik olarak) bir nesneyi dinamik olarak çağırmak istediğimde, kullanabilirim yansıma bu yönteme ele almak ve onu çağırmak için: DynamicObject cevap veren devralmasını tarafından nesneler dinamik yapılmış,Dinamik bir nesnede bir yöntemi dinamik olarak nasıl çağırabilirim?

typeof(Foo).GetMethod("Bar").Invoke(foo, new object[] { /* params */ }); 

Ancak üzere (tanımsız) örnek yöntemi TryInvokeMember kullanarak çağırır ve dinamik yöntemler sınıf maruz kalmaz yanıt açık nedenlerle, yansıma yoluyla. Bu, TryInvokeMember tarafından yanıtlanması gereken bir yöntem için bir yöntem tanıtıcısı alamam anlamına gelir.

İronik olarak, dynamic nesnesinde dinamik olmayan bir yöntemi, dynamic nesnesinde tanımlanmış bir yöntemi çağıracağınız kadar kolay bir şekilde dinamik olarak çağıramazsınız.

Doğrudan TryInvokeMember numaralı telefonu aramayı düşündüm, ancak ilk bağımsız değişken, soyut bir sınıf olan InvokeMemberBinder örneğinin olması gerekir. Dinamik bir nesne üzerinde dinamik bir yöntemi çağırmak için bir sınıf uygulamak zorunda kalırsam, yanlış bir şey yapmalıyım.

nasıl hedef sınıfı bunu uygulamıyor yapar bilerek adıyla bir dynamic nesne üzerinde bir yöntem çağırabilir ve TryInvokeMember kullanarak cevap gerektiğini?

cevap

9

Bunun için tek yol, C# derleyici çıktılarının dinamik nesnelerdeki yöntem çağrışımlarının çıktılarını taklit etmektir. Bu, Microsoft.CSharp.RuntimeBinder ad alanında [EditorBrowsable(EditorBrowsableState.Never)] işaretli bir grup türün kullanılmasını gerektirir, böylece Intellisense'de görünmezler. Söylemeye gerek yok, bu desteklenen bir senaryo gibi görünmüyor, bu yüzden kendi riski ile kullanın!

dynamic dynamicObject = new DerivedFromDynamicObject(); 
var callSiteBinder = Binder.InvokeMember(CSharpBinderFlags.None, "Bar", Enumerable.Empty<Type>(), typeof(Program), 
    new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); 
var callSite = CallSite<Action<CallSite, object>>.Create(callSiteBinder); 
callSite.Target(callSite, dynamicObject); 

This blog yayını ve this one arama siteleri ve bağlayıcı daha kanlı detayları sahiptir:

Bu kod DynamicObject türetilmiş bir sınıfın bir örneği üzerinde herhangi bir bağımsız değişken olarak dinamik Bar yöntemi çağırır.

+0

Sesler eğlenceli. Birisi gerçekten destekli bir çözümün olup olmadığını görmek için sabırsızlanıyorum çünkü bu çalışmayı durdurduğunda artık etrafta olmayacağım. – zneak

+1

Öte yandan, derleyicinin halihazırda yaptığı şeyden bu yana, çalışmayı hiç durduramayacaksınız, çünkü bu, bugün inşa edilen 'dynamic 'işlevini kullanarak herhangi bir uygulamayı öldürecek. – zneak

+0

@zneak Doğru, bunun oldukça güvenli bir bahis olduğunu düşünürdüm. Türlerin gizlendiğinden emin olmak için bu kadar büyük uzunluklara girmeleri şaşırtıcıdır. – Trillian

14

Dinamik bağlayıcı kodunu kapsülleyen açık kaynak (Apache lisansı) çerçevesi Dynamitey (nuget'te mevcut), bu çağrı sitelerini otomatik olarak önbelleğe almayı içerir. Her tür bağlayıcı için de kolaylık yöntemleri vardır (alıcılar, ayarlayıcılar, olaylar, dizinleyiciler, işleçler, dönüşümler), ancak özellikle InvokeMember'u istediğiniz gibi.

Dinamik bağlayıcı kodu, (derleme zamanında) statik olarak tanımlanmış sınıf üyeleri de çağrılırken yansıma (amortize edilmiş) hızından daha hızlı çalışır.

Dynamic.InvokeMember(foo,"Bar",arg...); 
+0

Bu çok havalı görünüyor! – zneak

+0

Man! Büyük nuget! Mükemmel çalışıyor! Teşekkür ederiz! cevap olarak işaretlenmelidir! – CodeHacker

+0

Harika bir paket, iş bitti. – Andro

İlgili konular