[C#] C #에서 리플렉션을 사용하여 문자열에서 속성 값 가져 오기

내 코드에서 Reflection 1 예제를 사용하여 데이터 변환을 구현하려고 합니다.

GetSourceValue함수에는 다양한 유형을 비교하는 스위치가 있지만 이러한 유형과 속성을 제거 GetSourceValue하고 단일 문자열 만 매개 변수로 사용하여 속성 값을 가져 오고 싶습니다 . 문자열에 클래스와 속성을 전달하고 속성 값을 확인하고 싶습니다.

이것이 가능한가?

원본 블로그 게시물의 1 웹 보관 버전



답변

 public static object GetPropValue(object src, string propName)
 {
     return src.GetType().GetProperty(propName).GetValue(src, null);
 }

물론, 당신은 유효성 검사를 추가하고 싶을 것입니다. 그러나 그것은 그 요점입니다.


답변

이런 식으로 어떻습니까 :

public static Object GetPropValue(this Object obj, String name) {
    foreach (String part in name.Split('.')) {
        if (obj == null) { return null; }

        Type type = obj.GetType();
        PropertyInfo info = type.GetProperty(part);
        if (info == null) { return null; }

        obj = info.GetValue(obj, null);
    }
    return obj;
}

public static T GetPropValue<T>(this Object obj, String name) {
    Object retval = GetPropValue(obj, name);
    if (retval == null) { return default(T); }

    // throws InvalidCastException if types are incompatible
    return (T) retval;
}

이를 통해 다음과 같이 단일 문자열을 사용하여 속성으로 내려갈 수 있습니다.

DateTime now = DateTime.Now;
int min = GetPropValue<int>(now, "TimeOfDay.Minutes");
int hrs = now.GetPropValue<int>("TimeOfDay.Hours");

이 메소드를 정적 메소드 또는 확장으로 사용할 수 있습니다.


답변

추가 Class:

public class Foo
{
    public object this[string propertyName]
    {
        get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
        set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
    }

    public string Bar { get; set; }
}

그런 다음 다음과 같이 사용할 수 있습니다.

Foo f = new Foo();
// Set
f["Bar"] = "asdf";
// Get
string s = (string)f["Bar"];


답변

네임 스페이스 ( )를 사용하는 CallByName것은 어떻습니까? 리플렉션을 사용하여 일반 객체, COM 객체 및 동적 객체의 속성, 필드 및 메서드를 가져옵니다.Microsoft.VisualBasicMicrosoft.VisualBasic.dll

using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;

그리고

Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString();


답변

jheddings에 의한 훌륭한 답변. propertyName이 property1.property2 [X] .property3가되도록 집계 된 배열 또는 객체 컬렉션을 참조 할 수 있도록 개선하고 싶습니다.

    public static object GetPropertyValue(object srcobj, string propertyName)
    {
        if (srcobj == null)
            return null;

        object obj = srcobj;

        // Split property name to parts (propertyName could be hierarchical, like obj.subobj.subobj.property
        string[] propertyNameParts = propertyName.Split('.');

        foreach (string propertyNamePart in propertyNameParts)
        {
            if (obj == null)    return null;

            // propertyNamePart could contain reference to specific 
            // element (by index) inside a collection
            if (!propertyNamePart.Contains("["))
            {
                PropertyInfo pi = obj.GetType().GetProperty(propertyNamePart);
                if (pi == null) return null;
                obj = pi.GetValue(obj, null);
            }
            else
            {   // propertyNamePart is areference to specific element 
                // (by index) inside a collection
                // like AggregatedCollection[123]
                //   get collection name and element index
                int indexStart = propertyNamePart.IndexOf("[")+1;
                string collectionPropertyName = propertyNamePart.Substring(0, indexStart-1);
                int collectionElementIndex = Int32.Parse(propertyNamePart.Substring(indexStart, propertyNamePart.Length-indexStart-1));
                //   get collection object
                PropertyInfo pi = obj.GetType().GetProperty(collectionPropertyName);
                if (pi == null) return null;
                object unknownCollection = pi.GetValue(obj, null);
                //   try to process the collection as array
                if (unknownCollection.GetType().IsArray)
                {
                    object[] collectionAsArray = unknownCollection as object[];
                    obj = collectionAsArray[collectionElementIndex];
                }
                else
                {
                    //   try to process the collection as IList
                    System.Collections.IList collectionAsList = unknownCollection as System.Collections.IList;
                    if (collectionAsList != null)
                    {
                        obj = collectionAsList[collectionElementIndex];
                    }
                    else
                    {
                        // ??? Unsupported collection type
                    }
                }
            }
        }

        return obj;
    }


답변

Ed S 의 코드를 사용 하면

보호 수준으로 인해 ‘ReflectionExtensions.GetProperty (Type, string)’에 액세스 할 수 없습니다

GetProperty()Xamarin.Forms에서 사용할 수없는 것 같습니다 . TargetFrameworkProfile입니다 Profile7내 휴대용 클래스 라이브러리 (.NET 프레임 워크 4.5, 윈도우 8, ASP.NET 코어 1.0, Xamarin.Android, Xamarin.iOS, Xamarin.iOS 클래식)에서.

이제 작동하는 솔루션을 찾았습니다.

using System.Linq;
using System.Reflection;

public static object GetPropValue(object source, string propertyName)
{
    var property = source.GetType().GetRuntimeProperties().FirstOrDefault(p => string.Equals(p.Name, propertyName, StringComparison.OrdinalIgnoreCase));
    return property?.GetValue(source);
}

출처


답변

중첩 속성 토론에 대해 DataBinder.Eval Method (Object, String)아래와 같이 사용하면 모든 반사 요소를 피할 수 있습니다.

var value = DataBinder.Eval(DateTime.Now, "TimeOfDay.Hours");

물론 System.Web어셈블리에 대한 참조를 추가해야 하지만 이것은 큰 문제는 아닙니다.