내 코드에서 Reflection 1 예제를 사용하여 데이터 변환을 구현하려고 합니다.
이 GetSourceValue
함수에는 다양한 유형을 비교하는 스위치가 있지만 이러한 유형과 속성을 제거 GetSourceValue
하고 단일 문자열 만 매개 변수로 사용하여 속성 값을 가져 오고 싶습니다 . 문자열에 클래스와 속성을 전달하고 속성 값을 확인하고 싶습니다.
이것이 가능한가?
답변
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.VisualBasic
Microsoft.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
어셈블리에 대한 참조를 추가해야 하지만 이것은 큰 문제는 아닙니다.
