ExpandoObject에 속성이 있는지 감지하는 방법은 무엇입니까?
자바 스크립트에서는 undefined 키워드를 사용하여 속성이 정의되어 있는지 확인할 수 있습니다.
if( typeof data.myProperty == "undefined" ) ...
C # ExpandoObject
에서 예외를 던지거나하지 않고 dynamic 키워드를 사용하여 어떻게합니까?
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를 구현하고 있지만 Github에서 선언되지 않은 속성에 대한 null 검사를 던지지 않는 동적 객체는 다음과 같다.
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
확장 메소드 를 작성하여 다음과 같은 작업을 수행 하려고했습니다 .
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");
or if your local variable is 'dynamic' you will have to cast it to ExpandoObject first.
// lookup is type 'dynamic'
object value = ((ExpandoObject)lookup).Value("PropertyBeingTested");
Depending on your use case, if null can be considered as being the same as undefined, you can turn your ExpandoObject into a 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"));
Output:
a is 1
b is 2.5
c is undefined
(authorDynamic as ExpandoObject).Any(pair => pair.Key == "YourProp");
Hey guys stop using Reflection for everything it costs a lots of CPU cycles.
Here is the solution:
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;
}
}
Try this one
public bool PropertyExist(object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName) != null;
}
참고URL : https://stackoverflow.com/questions/2839598/how-to-detect-if-a-property-exists-on-an-expandoobject
'IT' 카테고리의 다른 글
사용자의 현재 위치 / 좌표 얻기 (0) | 2020.05.21 |
---|---|
Android에서 대화 상자가 닫히거나 취소되는 것의 차이점은 무엇입니까? (0) | 2020.05.20 |
Angular 앱을 어떻게 배포합니까? (0) | 2020.05.20 |
Conda가 virtualenv의 필요성을 대체합니까? (0) | 2020.05.20 |
배열의 주소는 C의 값과 어떻게 다릅니 까? (0) | 2020.05.20 |