2012-09-28 15 views
5

एक वर्ग है कि DynamicObjectडायनामिक ऑब्जेक्ट के जंजीर मूल्य प्राप्त करना संभव है?

public class Test : DynamicObject 
{ 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     if (binder.Name == ("Posts")) 
     { 
      result = "property accessed was 'Posts'"; 
      return true; 
     } 

     return base.TryGetMember(binder, out result); 
    } 
} 

लागू करता बनाना मैं कॉल कर सकते हैं

dynamic test = new Test(); 
var result = test.Posts; 

और result का मूल्य है "गतिशील परीक्षण = नए टेस्ट(); वर परिणाम = test.Posts,"

यह ठीक है।

मैं क्या सोच रहा हूं, जब TryGetMember का आह्वान किया जाता है तो यह जंजीर मूल्य प्राप्त करना संभव है।

तो अगर मैं कहा जाता है:

if (binder.Name == ("Posts")) 
{ 
    if (... == "Load") 
     result = this.Load<Post>(... 123); 
    return true; 
} 

कि संभव तरह कुछ है:

dynamic test = new Test(); 
var result = test.Posts.Load(123); 

मैं तो जैसे कुछ कर सकते हैं? मैं इसे करने का कोई तरीका नहीं समझ सकता।

अब तक मेरे पास है:

class Program 
{ 
    static void Main(string[] args) 
    { 
     dynamic test = new Test(); 
     dynamic result = test.Posts.Load(123); 

     Console.WriteLine(result.Name); 

     dynamic result2 = test.Posts.Load(909); 

     Console.WriteLine(result2.Name); 

     Console.ReadKey(); 
    } 
} 

public class Test : DynamicObject 
{ 
    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     if (binder.Name == ("Posts")) 
     { 
      result = new ChainBuilder(this, "Post"); 
      return true; 
     } 

     return base.TryGetMember(binder, out result); 
    } 

    public T Load<T>(int id) where T : Post, new() 
    { 
     if (id == 123) 
      return new T {Id = 123, Name = "Bananas"}; 

     return new T {Id = 0, Name = "Others"}; 
    } 

    private class ChainBuilder : DynamicObject 
    { 
     public dynamic OriginalObject { get; set; } 
     public string PropertyInvoked { get; set; } 

     public ChainBuilder(DynamicObject originalObject, string propertyInvoked) 
     { 
      OriginalObject = originalObject; 
      PropertyInvoked = propertyInvoked; 
     } 

     public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) 
     { 
      if (binder.Name == "Load") 
      { 
       result = OriginalObject.Load<Post>((int)args[0]); 
       return true; 
      } 

      return base.TryInvokeMember(binder, args, out result); 
     } 
    } 
} 

public class Post 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

कौन सा बार्तोज़ करने के लिए धन्यवाद है।

लेकिन ऐसा लगता है कि यह मूल रूप से मार्क ने क्या प्रदान किया है।

मुझे एक अच्छा प्रारंभिक बिंदु दें! मैं इसे किसी अन्य सुझाव के लिए अभी खोल दूंगा।

यह सवाल

नहीं एक वास्तविक परियोजना में बदल गया है, बस प्रोटोटाइप लेकिन हासिल की है कि हम क्या चाहते थे।

उत्तर

3

मूल्यांकन का प्रत्येक चरण अलग है; यह .Posts.Load(123) का मूल्यांकन नहीं करता है - यह .Posts का मूल्यांकन करता है, और फिर अलग-अलग .Load(123) का मूल्यांकन करता है, इसलिए नहीं: आप इसे एक चरण में नहीं कर सकते हैं। चाल मान अपने आप को रचना के लिए, उदाहरण के लिए है:

using System; 
using System.Dynamic; 
using System.Text; 
static class Program { 
    static void Main() { 
     dynamic test = new Test(); 
     var result = test.Posts.Foo.Bar(123, "abc"); 
     Console.WriteLine(result); 
    } 
} 
public class Test : DynamicObject 
{ 
    public override bool TryGetMember(GetMemberBinder binder, 
     out object result) 
    { 
     result = new MemberAccessWrapper("member accessed was " + binder.Name); 
     return true; 
    } 
    private class MemberAccessWrapper : DynamicObject 
    { 
     private readonly string message; 
     public override bool TryInvoke(InvokeBinder binder, object[] args, 
      out object result) 
     { 
      StringBuilder builder = new StringBuilder(message).Append("("); 
      for(int i = 0 ; i < args.Length ; i++) { 
       if(i!=0)builder.Append(", "); 
       if (args[i] == null) { 
        builder.Append("null"); 
       } else if (args[i] is string) { 
        builder.Append("@\"").Append(((string)args[i]) 
         .Replace("\"", "\"\"")).Append("\""); 
       } else { 
        builder.Append(args[i]); 
       } 
      } 
      builder.Append(")"); 
      result = new MemberAccessWrapper(builder.ToString()); 
      return true; 
     } 
     public MemberAccessWrapper(string message) 
     { 
      this.message = message; 
     } 
     public override string ToString() 
     { 
      return message; 
     } 
     public override bool TryGetMember(GetMemberBinder binder, 
      out object result) 
     { 
      result = new MemberAccessWrapper(message + "." + binder.Name); 
      return true; 
     } 
    } 
} 
+0

बहुत बढ़िया, मैं बस अपना पोस्ट को संपादित करने गया था, जबकि तुम अपने पोस्ट की। धन्यवाद! – Phill

1

शायद आप इसे 'डायनामिक ऑब्जेक्ट' के बजाय मूल गतिशील इंटरफेस को कार्यान्वित करके इस तरह से कर सकते हैं, लेकिन सबसे आसान तरीका 'पोस्ट' के गतिशील आमंत्रण के लिए केवल एक और डायनामिक ऑब्जेक्ट लौटने के लिए है जो 'लोड' विधि को संभालेगा।

संबंधित मुद्दे