답변:
MSDN 에 따르면 선언은 IDictionary를 구현하고 있음을 보여줍니다.
public sealed class ExpandoObject : IDynamicMetaObjectProvider,
IDictionary<string, Object>, ICollection<KeyValuePair<string, Object>>,
IEnumerable<KeyValuePair<string, Object>>, IEnumerable, INotifyPropertyChanged
이를 사용하여 멤버가 정의되어 있는지 확인할 수 있습니다.
var expandoObject = ...;
if(((IDictionary<String, object>)expandoObject).ContainsKey("SomeMember")) {
// expandoObject.SomeMember exists.
}
여기서 중요한 구분이 필요합니다.
여기에있는 대부분의 답변은 질문에 언급 된 ExpandoObject에만 해당됩니다. 그러나 ASP.Net MVC ViewBag를 사용하는 경우 일반적인 사용법 (및 검색시이 질문에 해당하는 이유)이 있습니다. 이는 DynamicObject의 사용자 정의 구현 / 하위 클래스이므로 임의의 속성 이름을 null로 확인할 때 예외가 발생하지 않습니다. 다음과 같은 속성을 선언 할 수 있다고 가정하십시오.
@{
ViewBag.EnableThinger = true;
}
그런 다음 값을 확인하고 설정되어 있는지 여부를 확인하려고한다고 가정하십시오. 다음은 유효하고 컴파일되며 예외가 발생하지 않으며 올바른 답변을 제공합니다.
if (ViewBag.EnableThinger != null && ViewBag.EnableThinger)
{
// Do some stuff when EnableThinger is true
}
이제 EnableThinger 선언을 제거하십시오. 동일한 코드가 컴파일되고 올바르게 실행됩니다. 반사 할 필요가 없습니다.
ViewBag와 달리 존재하지 않는 속성에서 null을 확인하면 ExpandoObject가 발생합니다. MVC ViewBag의 부드러운 기능을 dynamic
객체에서 벗어나게 하려면 던져지지 않는 동적 구현을 사용해야합니다.
MVC ViewBag에서 정확한 구현을 간단히 사용할 수 있습니다.
. . .
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = ViewData[binder.Name];
// since ViewDataDictionary always returns a result even if the key does not exist, always return true
return true;
}
. . .
MVC ViewPage에서 MVC 뷰에 묶여있는 것을 볼 수 있습니다.
http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/ViewPage.cs
DynamicViewDataDictionary의 올바른 동작의 핵심은 ViewDataDictionary의 Dictionary 구현입니다.
public object this[string key]
{
get
{
object value;
_innerDictionary.TryGetValue(key, out value);
return value;
}
set { _innerDictionary[key] = value; }
}
https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System.Web.Mvc/ViewDataDictionary.cs
다시 말해서, 그것은 그것이 무엇이든 관계없이 항상 모든 키에 대한 값을 반환합니다-아무것도 없을 때 단순히 null을 반환합니다. 그러나 ViewDataDictionary는 MVC의 모델에 연결해야하는 부담이 있으므로 MVC 뷰 외부에서 사용하기 위해 우아한 사전 부분 만 제거하는 것이 좋습니다.
여기에 모든 내장을 실제로 게시하기에는 너무 길다. 대부분 IDictionary를 구현하고 있지만 DDict
Github에서 선언되지 않은 속성에 대한 null 검사를 던지지 않는 동적 객체 (class )가 있습니다.
https://github.com/b9chris/GracefulDynamicDictionary
NuGet을 통해 프로젝트에 추가하려는 경우 이름은 GracefulDynamicDictionary 입니다.
최근에 비슷한 질문에 대답했습니다. 동적 객체의 멤버를 어떻게 반영합니까?
곧 ExpandoObject가 유일한 동적 객체는 아닙니다. 리플렉션은 정적 유형 (IDynamicMetaObjectProvider를 구현하지 않는 유형)에서 작동합니다. 이 인터페이스를 구현하는 유형의 경우 리플렉션은 기본적으로 쓸모가 없습니다. ExpandoObject의 경우 기본 사전에서 속성이 키로 정의되어 있는지 간단히 확인할 수 있습니다. 다른 구현에서는 어려울 수 있으며 때로는 유일한 방법은 예외로 작업하는 것입니다. 자세한 내용은 위의 링크를 참조하십시오.
업데이트 됨 : 대리자를 사용하고 동적 개체 속성이있는 경우 값을 가져 오려고 시도 할 수 있습니다. 속성이 없으면 단순히 예외를 잡아서 false를 반환합니다.
한번보세요, 그것은 나를 위해 잘 작동합니다 :
class Program
{
static void Main(string[] args)
{
dynamic userDynamic = new JsonUser();
Console.WriteLine(IsPropertyExist(() => userDynamic.first_name));
Console.WriteLine(IsPropertyExist(() => userDynamic.address));
Console.WriteLine(IsPropertyExist(() => userDynamic.last_name));
}
class JsonUser
{
public string first_name { get; set; }
public string address
{
get
{
throw new InvalidOperationException("Cannot read property value");
}
}
}
static bool IsPropertyExist(GetValueDelegate getValueMethod)
{
try
{
//we're not interesting in the return value. What we need to know is whether an exception occurred or not
getValueMethod();
return true;
}
catch (RuntimeBinderException)
{
// RuntimeBinderException occurred during accessing the property
// and it means there is no such property
return false;
}
catch
{
//property exists, but an exception occurred during getting of a value
return true;
}
}
delegate string GetValueDelegate();
}
코드 출력은 다음과 같습니다.
True
True
False
IsPropertyExist
. 이 예제에서는을 던질 수 있음을 알고 있습니다 InvalidOperationException
. 실제로 어떤 예외가 발생할 수 있는지 전혀 모릅니다. 화물 숭배를 막기 위해 +1.
확장 메소드 를 작성하여 다음과 같은 작업을 수행 하려고했습니다 .
dynamic myDynamicObject;
myDynamicObject.propertyName = "value";
if (myDynamicObject.HasProperty("propertyName"))
{
//...
}
...하지만 ExpandoObject
C # 5 설명서 에 따라 확장 프로그램을 만들 수 없습니다 (자세한 내용은 여기 ).
그래서 나는 클래스 도우미를 만들었습니다.
public static class ExpandoObjectHelper
{
public static bool HasProperty(ExpandoObject obj, string propertyName)
{
return ((IDictionary<String, object>)obj).ContainsKey(propertyName);
}
}
그것을 사용하려면 :
// If the 'MyProperty' property exists...
if (ExpandoObjectHelper.HasProperty(obj, "MyProperty"))
{
...
}
유형이 적절한 예를 얻기 위해 Reflection을 사용하고 싶지 않은 이유는 무엇입니까? 이렇게
dynamic v = new Foo();
Type t = v.GetType();
System.Reflection.PropertyInfo[] pInfo = t.GetProperties();
if (Array.Find<System.Reflection.PropertyInfo>(pInfo, p => { return p.Name == "PropName"; }). GetValue(v, null) != null))
{
//PropName initialized
}
이 확장 메서드는 속성이 있는지 확인한 다음 값 또는 null을 반환합니다. 이 기능은 응용 프로그램에서 불필요한 예외를 발생시키지 않도록하는 데 도움이됩니다.
public static object Value(this ExpandoObject expando, string name)
{
var expandoDic = (IDictionary<string, object>)expando;
return expandoDic.ContainsKey(name) ? expandoDic[name] : null;
}
다음과 같이 사용할 수있는 경우 :
// lookup is type 'ExpandoObject'
object value = lookup.Value("MyProperty");
또는 지역 변수가 '동적'인 경우 먼저 ExpandoObject로 캐스트해야합니다.
// lookup is type 'dynamic'
object value = ((ExpandoObject)lookup).Value("PropertyBeingTested");
사용 사례에 따라 null이 정의되지 않은 것과 동일한 것으로 간주 될 수있는 경우 ExpandoObject를 DynamicJsonObject로 전환 할 수 있습니다.
dynamic x = new System.Web.Helpers.DynamicJsonObject(new ExpandoObject());
x.a = 1;
x.b = 2.50;
Console.WriteLine("a is " + (x.a ?? "undefined"));
Console.WriteLine("b is " + (x.b ?? "undefined"));
Console.WriteLine("c is " + (x.c ?? "undefined"));
산출:
a is 1
b is 2.5
c is undefined
이봐, 많은 CPU 사이클을 소비하는 모든 것에 대해 Reflection 사용을 중단하십시오.
해결책은 다음과 같습니다.
public class DynamicDictionary : DynamicObject
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get
{
return dictionary.Count;
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
string name = binder.Name;
if (!dictionary.TryGetValue(binder.Name, out result))
result = "undefined";
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
이거 한번 해봐
public bool PropertyExist(object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName) != null;
}
dynamic
(항상 리턴 null
).
data.myProperty
; 의 값을 확인하지 않습니다 . 어떤typeof data.myProperty
결과를 반환 하는지 확인 합니다. 그것은 그 정확data.myProperty
존재하고 설정할 수undefined
있지만,이 경우,typeof
이외를 반환합니다"undefined"
. 따라서이 코드는 작동합니다.