[C#] 동적 객체의 멤버를 어떻게 반영합니까?

.NET 4의 dynamic 키워드로 선언 된 객체에서 속성 사전과 값을 가져와야합니까? 이것은 반사를 사용하여 작동하지 않는 것 같습니다.

예:

dynamic s = new ExpandoObject();
s.Path = "/Home";
s.Name = "Home";

// How do I enumerate the Path and Name properties and get their values?
IDictionary<string, object> propertyValues = ???



답변

IDynamicMetaObjectProvider가 동적 멤버 이름을 제공 할 수있는 경우이를 가져올 수 있습니다. 참조 은 getMemberNames의 아파치에서 구현 PCL 라이브러리 라이센스 Dynamitey을 (nuget에서 찾을 수있는), 그것은 작동 ExpandoObject들과 DynamicObject그 구현이야 GetDynamicMemberNames및 기타 IDynamicMetaObjectProvider의 구현과 메타 오브젝트를 제공하는 사람 GetDynamicMemberNames정의가 이상을 테스트하지 않고 is IDynamicMetaObjectProvider.

멤버 이름을 얻은 후에는 올바른 방법으로 값을 얻는 것이 약간 더 효과적이지만 Impromptu는이 작업을 수행하지만 흥미로운 부분을 지적하고 이해하기가 더 어렵습니다. 여기 문서가 있으며 리플렉션보다 빠르거나 빠르지 만 expando의 사전 조회보다 빠를 것 같지는 않지만 모든 객체, expando, dynamic 또는 original에서 작동합니다.


답변

ExpandoObject의 경우 ExpandoObject 클래스는 실제로 IDictionary<string, object>해당 속성을 구현 하므로 솔루션은 캐스팅만큼 간단합니다.

IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;

일반 동적 객체에는 작동하지 않습니다. 이 경우 IDynamicMetaObjectProvider를 통해 DLR로 드롭 다운해야합니다.


답변

고려해야 할 몇 가지 시나리오가 있습니다. 우선, 객체의 유형을 확인해야합니다. 이를 위해 간단히 GetType ()을 호출 할 수 있습니다. 유형이 IDynamicMetaObjectProvider를 구현하지 않으면 다른 객체와 동일한 리플렉션을 사용할 수 있습니다. 다음과 같은 것 :

var propertyInfo = test.GetType().GetProperties();

그러나 IDynamicMetaObjectProvider 구현의 경우 단순 리플렉션이 작동하지 않습니다. 기본적으로이 객체에 대해 더 알아야합니다. 그것이 ExpandoObject (IDynamicMetaObjectProvider 구현 중 하나) 인 경우 itowlson이 제공 한 답변을 사용할 수 있습니다. ExpandoObject는 속성을 사전에 저장하고 동적 객체를 사전에 캐스트 할 수 있습니다.

DynamicObject (다른 IDynamicMetaObjectProvider 구현) 인 경우이 DynamicObject가 노출하는 모든 방법을 사용해야합니다. DynamicObject는 실제로 속성 목록을 어디에나 “저장”할 필요가 없습니다. 예를 들어 다음과 같은 작업을 수행 할 수 있습니다 ( 블로그 게시물 의 예를 재사용하고 있음 ).

public class SampleObject : DynamicObject
{
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = binder.Name;
        return true;
    }
}

이 경우 지정된 이름으로 속성에 액세스하려고 할 때마다 개체는 속성 이름을 문자열로 반환합니다.

dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".

따라서 반영 할 항목이 없습니다.이 개체에는 속성이 없으며 동시에 모든 유효한 속성 이름이 작동합니다.

IDynamicMetaObjectProvider 구현의 경우 ExpandoObject와 같은 속성 목록을 가져오고 나머지 부분은 무시하거나 예외를 throw 할 수있는 알려진 구현을 필터링해야합니다.


답변

Newtonsoft Json.Net 필요

조금 늦었지만 나는 이것을 생각해 냈습니다. 그것은 단지 당신에게 키를 제공하고 당신은 역동적 인 것들을 사용할 수 있습니다 :

public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
{
    JObject attributesAsJObject = dynamicToGetPropertiesFor;
    Dictionary<string, object> values = attributesAsJObject.ToObject<Dictionary<string, object>>();
    List<string> toReturn = new List<string>();
    foreach (string key in values.Keys)
    {
        toReturn.Add(key);
    }
    return toReturn;
}

그런 다음 간단히 다음과 같이 가르칩니다.

foreach(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor))
{
    dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName];
    // And
    dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value
}

값을 문자열 또는 다른 객체로 가져 오거나 다른 동적 작업을 수행하고 조회를 다시 사용하도록 선택합니다.


답변