2012-09-28 29 views
5

Tạo một lớp mà thực hiện DynamicObjectCó thể nhận giá trị chuỗi của DynamicObject không?

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

tôi có thể gọi

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

Và giá trị của result là "năng động thử nghiệm = new Test(); var result = test.Posts;"

Tốt thôi.

Điều tôi đang tự hỏi là, khi TryGetMember được gọi là có thể lấy giá trị chuỗi.

Vì vậy, nếu tôi gọi:

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

Sau đó tôi có thể làm điều gì đó như:

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

là một cái gì đó như thế có thể? Tôi không thể tìm ra cách để làm điều đó.

Cho đến nay tôi có:

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

Đó là nhờ vào Bartosz.

Nhưng có vẻ như về cơ bản những gì Marc đã cung cấp.

Hãy cho tôi một điểm khởi đầu tốt! Bây giờ tôi sẽ để nó mở cho bất kỳ gợi ý nào khác.

Câu hỏi này đã dẫn đến

Không phải là một dự án thực tế, chỉ cần prototyping nhưng đạt được những gì chúng tôi muốn.

Trả lời

3

Mỗi bước đánh giá là riêng biệt; nó không đánh giá .Posts.Load(123) - nó đánh giá .Posts và sau đó đánh giá riêng .Load(123), vì vậy không: bạn không thể thực hiện việc này trong một bước. Bí quyết là tự soạn các giá trị, ví dụ:

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

Tuyệt vời, tôi vừa chỉnh sửa bài đăng của mình khi bạn đăng bài của bạn. Cảm ơn! – Phill

1

Có lẽ bạn có thể thực hiện theo cách này bằng cách triển khai các giao diện động cơ bản thay vì 'DynamicObject', nhưng cách đơn giản nhất là cho lời gọi động của 'Bài đăng' để trả về một DynamicObject khác sẽ xử lý phương thức 'Tải'.

Các vấn đề liên quan