2013-02-11 17 views
7

Ben bir explorer nesnesiyle çalışıyorum ve hesaplanmış bir özellik tanımlamaya çalışıyorum.Bir expando nesnesinde hesaplanan özellik tanımlayın

Ben aşağıdaki gibi bir şey yaparak basit bir özellik tanımlamak biliyoruz: Aynı şekilde

dynamic myExpando = new ExpandoObject(); 
myExpando.TheAnswerToLifeTheUniverseAndEverything= 42; 

, ben de bir yöntem tanımlayabilirsiniz:

myExpando.GetTheQuestion = ((Func<string>)(() => 
     { 
      return "How many road must a man walk down before we can call him a man?"; 
     })); 

standart bir nesne ile çalışan biz hesaplanan bir özelliği tanımlayabilir, yani özel bir yöntem/calc sonucunu döndürecek bir özellik tanımlayabilir. Bir örneğe gerek yok.

Benim genomda benzer bir şey yapmam gerekiyor - aslında bir "Func" (veya başka bir temsilci türü olarak adlandırılan, özel bir yöntem çağırabilir ve özel bir dönüş türü varsa en kısa sürede gider) özelliği olan bir özelliğe sahip olmak gerekir. . Yani temelde ikinci örnekte olduğu gibi bir yöntem çağırmak gerekir ama bir özellik gibi çalışın.

Temelde ben mülkiyet organı olarak bir özel temsilci tanımlama yeteneği tutarken, myExpando.GetTheQuestion yerine myExpando.GetTheQuestion() ile adlandırmak gerekiyor.

Bunu yapmanın bir yolu var mı? Ben bunu İfade ağaçlarını kullanarak yapabilirim, ama itiraf etmeliyim ki orada biraz kayboldum. Bunu nasıl başaracağınıza dair herhangi bir rehber olabilir mi? Ben yukarıda imkansız olduğunu düşünmeye başladım bilmiyorum bazı çok özel sınıf/arabirim/sözdizim olmadığı sürece


DÜZENLEME .. biraz daha araştırma Yapıldı. Anladığım kadarıyla, ExpandoObject sınıfı arka plan sıhhi tesisatını yapan bazı yöntemleri tanımlayarak çalışır: TryGetMember, TrySetMember ve benzeri. Artık dinamik objetc'de "bir mülke erişildiğinde", TryGetMember, aranan kişi. Bu üye bir tür içsel sözlükten bir değer döndürür (evet, biliyorum ... bu biraz basitleştirilmiş ama bu fikri vermeli) ... döndürülen değer türü üzerinde bir test yok. Bu, benim örneğimde myExpando.GetTheQuestion'un orijinal Func değerini döndüreceği anlamına gelir.

TryGetMember yalnızca bir değer döndürdüğünden, özellik kodunu "yürütmesini" sağlamanın bir yolu yoktur. Bunu başarmak için, aslında bir yöntemin SONUÇ olduğu bir ifade/lambda/func/action vekiline ihtiyacınız olacaktır. Hangi imkansız gözüküyor (bir şeyleri kaçırmadıkça pek bir şey ifade etmeyecek - temelde bir 'temsilci' olarak ayarlanmış bir değere sahip olacaksınız ve sonra delege dönüş değeri olarak elde edeceksiniz). Doğru muyum, yoksa bir şey mi özlüyorum? binder.Name altında özel Dictionary<string,object> değeri saklamak ve bu sözlükten geri almak için TryGetMember kullanmak DynamicObject ve

public override bool TryGetMember(GetMemberBinder binder, out object result) ağır basan

ve public override bool TrySetMember(SetMemberBinder binder, object value)

Uygulamak TrySetMember devralan tarafından

cevap

2
Sen kendi ExpandoObject yapmak gerekir

, Bu size temel bir ExpandoObject verecek.Ardından, ihtiyacınız olan özelliği vermek için, TryGetMember numaralı belgeye bir nesne ekledikten sonra, nesneyi çektikten sonra, öğesinin olup olmadığını kontrol edin ve sonra herhangi bir bağımsız değişkenin alınmadığını görmek için yansımayı kullanın. Her ikisi de doğruysa, dynamic'a dönün ve arg çağırma parantezi eklemeyin ve result'a atayın.

public override bool TryGetMember(GetMemberBinder binder, out object result) 
{ 
     if (_dictionary.TryGetValue(binder.Name, out result)){ 
      if(result is Delegate && /* some reflection check on args*/){ 
       result = ((dynamic)result)(); 
      } 
     } 
} 

ben sahiptir (Nuget olarak) bir açık kaynak çerçevesinde ImpromptuInterface sahip bir olmayan mühürlü ImpromptuDictionary Eğer ExpandoObject olarak bunun yerine, ExpandoObject böyle daha nüanslı özelliklerine ihtiyaçları özellikle birlikte başlayabileceğini hangi gui bağlama desteği olarak. Ayrıca yararlı bulabileceğiniz daha fazla dlr plumbing features var.

+0

Evet, aslında benzer bir çözümden bahsediyorum - ama bunun, özel kod olmadan (ekleyemediğimden değil - genişletme nesnesinin tamamı zaten bir özel miras sınıfı olduktan sonra) ifade kullanılarak mümkün olabileceğini merak ediyorum ağaçlar ve benzeri. Neyse, başka bir yol yayınlanmayacaksa, bunu en uygun şekilde kabul edeceğim^_^ – SPArchaeologist

+0

Tamam, şimdilik bunu kabul edeceğim. Bu bir çözümdür, ancak "hesaplanan özellik" in normal bir özellik gibi davranmasının da tek yolu olduğunu düşünüyorum. Diğer davranışları desteklemek için temel genişletmeyi genişletdiğimden (tanımlanamayan özellikler için null döndüren güvenli bir genişletme kullanıyorum), sanırım bununla başa çıkabilirim (aslında bu benim ilk fikrimdi, ama yine de soruyu yanıtladım) bir şey eksik olsaydım). Teşekkürler jbtule, ben de lib'inize bir göz atacağım - her zaman öğrenecek bir şey var. – SPArchaeologist