Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
993 views
in Technique[技术] by (71.8m points)

dynamic - Treat Object Like Dictionary of Properties in C#

I want to be able to access property values in an object like a dictionary, using the name of the property as a key. I don't really care if the values are returned as objects, so Dictionary<string, object> is fine. This is the intended usage:

object person = new { Name: "Bob", Age: 45 };
IDictionary<string, object> lookup = new PropertyDictionary(person);
string name = (string)person["Name"];
person["Age"] = (int)person["Age"] + 1; // potentially editable

I was about to implement my own class for this, but then I started noticing classes like DynamicObject implement the IDictionary interface, which made think this was already being done for me somewhere.

What I want is similar to the functionality used by ASP.NET MVC that allows using anonymous types to set HTML tag attributes. I have a lot of classes that use dictionaries as data sources, but most of the time I should be able to pass in objects as well.

Since this is for a general-purpose library, I thought I would create a reusable class that simply decorated an object with the IDictionary interface. It will save me from creating an explosion of overloads.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I don't believe there is a built-in .Net type like this already in the .Net framework. It seems like you really want to create an object that behaves a lot like a Javascript object. If so then deriving from DynamicObject may be the right choice. It allows you to create an object which when wrapped with dynamic allows you to bind directly obj.Name or via the indexer obj["Name"].

public class PropertyBag : DynamicObject {
  private object _source;
  public PropertyBag(object source) {
    _source = source;
  }
  public object GetProperty(string name) {  
    var type = _source.GetType();
    var property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    return property.GetValue(_source, null);
  }
  public override bool TryGetMember(GetMemberBinder binder, out object result) {
    result = GetProperty(binder.Name);
    return true;
  }
  public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) {
    result = GetProperty((string)indexes[0]);
    return true;
  }
}

You can use this to wrap any type and use both the indexer and name syntax to get the properties

var student = new Student() { FirstName = "John", LastName = "Doe" };
dynamic bag = new PropertyBag(student);
Console.WriteLine(bag["FirstName"]);  // Prints: John
Console.WriteLine(bag.FirstName);     // Prints: John

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...