2012-03-11 2 views
14

속성 이름을 키로 사용하여 사전과 같은 개체의 속성 값에 액세스 할 수 있기를 원합니다. 값이 객체로 반환되는지는 상관하지 않으므로 Dictionary<string, object>이 좋습니다. 이것은 의도 된 용도입니다 :C#의 속성 사전처럼 개체 처리

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 

나는이에 대한 내 자신의 클래스를 구현하고 있었다, 그러나 나는 DynamicObject 같은 수업이 이미 어딘가에 나를 위해 수행되고 있던 생각 만든 IDictionary 인터페이스를 구현 몰래 시작했다.

내가 원하는 것은 익명 형식을 사용하여 HTML 태그 특성을 설정할 수있는 ASP.NET MVC에서 사용되는 기능과 비슷합니다. 나는 사전을 데이터 소스로 사용하는 많은 수업을 가지고 있지만 대부분의 경우 객체를 전달할 수 있어야합니다.

일반용 library 용이므로 IDictionary 인터페이스로 개체를 장식 한 재사용 가능한 클래스를 만들 것이라고 생각했습니다. 과부하가 폭발하는 것을 막을 수 있습니다.

+0

뭔가 ...는 http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx – Lloyd

답변

18

내가이 믿지 않는 내장 된 닷넷 프레임 워크에서 이미이 같은 닷넷 유형입니다. Javascript 객체처럼 많이 동작하는 객체를 만들고 싶습니다. 그렇다면 DynamicObject에서 파생되는 것이 올바른 선택 일 수 있습니다. dynamic으로 랩핑하면 obj.Name을 직접 바인딩하거나 인덱서 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; 
    } 
} 
당신은 어떤 종류의 포장 및 속성을 얻기 위해 인덱서와 이름 구문을 모두 사용하려면이 옵션을 사용할 수 있습니다

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 
+0

DynamicObject를 상속받지 않고 비슷하게했습니다. IDictionary에서 상속 받았으며 인덱싱 만 지원합니다. 필요한 모든 것입니다. –

+0

ExpandoObject를 보았습니까? http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx – Scott

+1

ExpandoObject는 처음부터 시작하는 경우에만 작동합니다. –

1

동적 키워드가 하나의 옵션이 될 수 있습니다. 동적 언어 런타임을 사용합니다. 런타임에 프로그램에서 가장 근접한 유형을 찾습니다. can not이면 동적 유형을 dictionay 오브젝트로 변환합니다. 여기서 key는 특성의 이름이고 value는 특성의 값입니다.

은 MSDN의 다음 링크를 따르

Using dynamic keyword in C#
dynamic (C# Reference)
DLR Overview
usage of dynamic sample walkthough page

+0

유일한 문제는 내가 수용하기위한 모든 내 구현을 수정해야 할 것입니다 역동적 인 사람. 게다가 obj [ "Name"]가 동적 인 인덱서에 대한 호출로 해석 될 것이기 때문에 이름으로 속성을 참조하는 방법을 모르겠습니다. –

+0

당신은 직접 사전에 갈 수 없습니까? 자신 만의 구현을하면 일이 엉망진창이 될 수 있습니다 ... 제가 강조하는 것은 인덱서를 통해 자동으로 사전으로 변환되는 클래스를 원한다는 것입니다. 문자열 형식의 매개 변수로 인덱서를 만들려고 했습니까? – Uday0119

+0

개체를 래핑하고 사전에 복사하지 않으려합니다. 아이디어는 IDictionary가 예상되는 개체를 전달하는 것입니다. 그렇게하면 사전이 예상되는 익명 형식을 사용할 수 있습니다. –

8

아마 간단한 그것을 얻을 수 있습니다,이 확장 방법이 있습니다

이제
public static Dictionary<string, object> ToPropertyDictionary(this object obj) 
{ 
    var dictionary = new Dictionary<string, object>(); 
    foreach (var propertyInfo in obj.GetType().GetProperties()) 
     if (propertyInfo.CanRead && propertyInfo.GetIndexParameters().Length == 0) 
      dictionary[propertyInfo.Name] = propertyInfo.GetValue(obj, null); 
    return dictionary; 
} 

당신은 할 수 있습니다 :

object person = new { Name = "Bob", Age = 45 }; 
var lookup = person.ToPropertyDictionary(); 
string name = (string)lookup["Name"]; 
lookup["Age"] = (int)lookup["Age"] + 1; // indeed editable 

참고 :

이 사전은 대소 문자를 구분
  1. 가 (당신이 하찮게는 바로 StringComparer을 통과 확장 할 수 있습니다).

  2. 인덱서 (속성이기도 함)는 무시하지만 사용자가 직접 작업해야합니다.

  3. 내부적으로 obj.GetType을 호출하기 때문에이 방법이 복싱에 도움이되지 않는다고 생각하면이 방법은 일반적이지 않으므로 그 시점에서 상자에 표시됩니다.

  4. "읽을 수있는"속성 만 가져옵니다 (그렇지 않으면 보유 된 값을 가져 오지 못합니다). "쓰기 가능"이되기를 원하면 CanWrite 플래그도 사용해야합니다. MSDN에 인덱싱과 같은