나는리플렉션을 사용한 데이터 변환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"];
SetValue
과GetValue
메소드는 다음과 함께 작동합니다.Object
. 특정 유형으로 작업해야하는 경우GetValue
그것을 배정 할 값을 던져라.SetValue
- Eduardo Cuomo
무엇을 사용 하는가?CallByName
~의Microsoft.VisualBasic
네임 스페이스 (Microsoft.VisualBasic.dll
)? 리플렉션을 사용하여 일반 오브젝트, COM 오브젝트 및 동적 오브젝트의 특성, 필드 및 메소드를 가져옵니다.
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 Array[];
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;
}
에서 코드를 사용하는 경우에드 S.나는 얻다
'ReflectionExtensions.GetProperty (유형, 문자열)'보호 수준으로 인해 액세스 할 수 없습니다.
그것은 보인다GetProperty()
Xamarin.Forms에서는 사용할 수 없습니다.TargetFrameworkProfile
~이다.Profile7
내 휴대용 클래스 라이브러리 (.NET Framework 4.5, Windows 8, ASP.NET 코어 1.0, Xamarin.Android, Xamarin.iOS, Xamarin.iOS Classic)
이제는 실질적인 해결책을 찾았습니다.
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
어셈블리,하지만 이것은 아마도 큰 문제가되지 않습니다.
.NET 표준에서는 호출 방법이 변경되었습니다 (1.6 기준). 또한 C #6의 null 조건부 연산자를 사용할 수 있습니다.
using System.Reflection;
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetRuntimeProperty(propName)?.GetValue(src);
}
? operator
- blfuentes
의 PropertyInfo 사용하기System.Reflection네임 스페이스. 리플렉션은 우리가 액세스하려고하는 속성에 상관없이 올바르게 컴파일됩니다. 런타임 중에 오류가 발생합니다.
public static object GetObjProperty(object obj, string property)
{
Type t = obj.GetType();
PropertyInfo p = t.GetProperty("Location");
Point location = (Point)p.GetValue(obj, null);
return location;
}
그것은 개체의 위치 속성을 얻으려면 잘 작동합니다.
Label1.Text = GetObjProperty(button1, "Location").ToString();
위치를 알려 드리겠습니다 : {X = 71, Y = 27} 같은 방식으로 location.X 또는 location.Y를 반환 할 수도 있습니다.
public static List<KeyValuePair<string, string>> GetProperties(object item) //where T : class
{
var result = new List<KeyValuePair<string, string>>();
if (item != null)
{
var type = item.GetType();
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var pi in properties)
{
var selfValue = type.GetProperty(pi.Name).GetValue(item, null);
if (selfValue != null)
{
result.Add(new KeyValuePair<string, string>(pi.Name, selfValue.ToString()));
}
else
{
result.Add(new KeyValuePair<string, string>(pi.Name, null));
}
}
}
return result;
}
이 방법은 List에 값이있는 모든 속성을 가져 오는 방법입니다.
여기에 문자열이 중첩 경로를 알려주지 않아도되는 중첩 된 속성을 찾는 또 다른 방법이 있습니다. 단일 속성 방법에 대한 Ed S.의 공헌
public static T FindNestedPropertyValue<T, N>(N model, string propName) {
T retVal = default(T);
bool found = false;
PropertyInfo[] properties = typeof(N).GetProperties();
foreach (PropertyInfo property in properties) {
var currentProperty = property.GetValue(model, null);
if (!found) {
try {
retVal = GetPropValue<T>(currentProperty, propName);
found = true;
} catch { }
}
}
if (!found) {
throw new Exception("Unable to find property: " + propName);
}
return retVal;
}
public static T GetPropValue<T>(object srcObject, string propName) {
return (T)srcObject.GetType().GetProperty(propName).GetValue(srcObject, null);
}
Type.GetProperty
보고null
전화하는 대신GetValue
~과NullReferenceException
루프에 던졌습니다. - Groo
당신은 어떤 객체를 검사하는지 언급하지 않으며 주어진 객체를 참조하는 객체를 거부하기 때문에 정적 인 객체를 의미한다고 가정합니다.
using System.Reflection;
public object GetPropValue(string prop)
{
int splitPoint = prop.LastIndexOf('.');
Type type = Assembly.GetEntryAssembly().GetType(prop.Substring(0, splitPoint));
object obj = null;
return type.GetProperty(prop.Substring(splitPoint + 1)).GetValue(obj, null);
}
로컬 변수로 검사중인 객체를 표시했음을 주목하십시오.obj
.null
정적을 의미하고, 그렇지 않으면 원하는대로 설정하십시오. 또한GetEntryAssembly()
"실행중인"어셈블리를 가져 오는 데 사용할 수있는 몇 가지 방법 중 하나입니다. 유형을로드하는 데 어려움을 겪고있는 경우 해당 어셈블리를 가지고 놀고 싶을 수 있습니다.
다음 코드는 객체 인스턴스에 포함 된 모든 속성 이름 및 값의 전체 계층 구조를 표시하는 재귀 적 메서드입니다. 이 방법은 단순화 된 버전의 AlexD 'sGetPropertyValue()
이 스레드에서 위의 대답. 이 토론 스레드 덕분에이 작업을 수행하는 방법을 알 수있었습니다.
예를 들어,이 메소드를 사용하여 a에서 모든 속성의 폭발 또는 덤프를 표시합니다.WebService
다음과 같이 메소드를 호출하여 응답을 보냅니다.
PropertyValues_byRecursion("Response", response, false);
public static object GetPropertyValue(object srcObj, string propertyName)
{
if (srcObj == null)
{
return null;
}
PropertyInfo pi = srcObj.GetType().GetProperty(propertyName.Replace("[]", ""));
if (pi == null)
{
return null;
}
return pi.GetValue(srcObj);
}
public static void PropertyValues_byRecursion(string parentPath, object parentObj, bool showNullValues)
{
/// Processes all of the objects contained in the parent object.
/// If an object has a Property Value, then the value is written to the Console
/// Else if the object is a container, then this method is called recursively
/// using the current path and current object as parameters
// Note: If you do not want to see null values, set showNullValues = false
foreach (PropertyInfo pi in parentObj.GetType().GetTypeInfo().GetProperties())
{
// Build the current object property's namespace path.
// Recursion extends this to be the property's full namespace path.
string currentPath = parentPath + "." + pi.Name;
// Get the selected property's value as an object
object myPropertyValue = GetPropertyValue(parentObj, pi.Name);
if (myPropertyValue == null)
{
// Instance of Property does not exist
if (showNullValues)
{
Console.WriteLine(currentPath + " = null");
// Note: If you are replacing these Console.Write... methods callback methods,
// consider passing DBNull.Value instead of null in any method object parameters.
}
}
else if (myPropertyValue.GetType().IsArray)
{
// myPropertyValue is an object instance of an Array of business objects.
// Initialize an array index variable so we can show NamespacePath[idx] in the results.
int idx = 0;
foreach (object business in (Array)myPropertyValue)
{
if (business == null)
{
// Instance of Property does not exist
// Not sure if this is possible in this context.
if (showNullValues)
{
Console.WriteLine(currentPath + "[" + idx.ToString() + "]" + " = null");
}
}
else if (business.GetType().IsArray)
{
// myPropertyValue[idx] is another Array!
// Let recursion process it.
PropertyValues_byRecursion(currentPath + "[" + idx.ToString() + "]", business, showNullValues);
}
else if (business.GetType().IsSealed)
{
// Display the Full Property Path and its Value
Console.WriteLine(currentPath + "[" + idx.ToString() + "] = " + business.ToString());
}
else
{
// Unsealed Type Properties can contain child objects.
// Recurse into my property value object to process its properties and child objects.
PropertyValues_byRecursion(currentPath + "[" + idx.ToString() + "]", business, showNullValues);
}
idx++;
}
}
else if (myPropertyValue.GetType().IsSealed)
{
// myPropertyValue is a simple value
Console.WriteLine(currentPath + " = " + myPropertyValue.ToString());
}
else
{
// Unsealed Type Properties can contain child objects.
// Recurse into my property value object to process its properties and child objects.
PropertyValues_byRecursion(currentPath, myPropertyValue, showNullValues);
}
}
}
Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType)
public static TValue GetFieldValue<TValue>(this object instance, string name)
{
var type = instance.GetType();
var field = type.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.FieldType) && e.Name == name);
return (TValue)field?.GetValue(instance);
}
public static TValue GetPropertyValue<TValue>(this object instance, string name)
{
var type = instance.GetType();
var field = type.GetProperties(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance).FirstOrDefault(e => typeof(TValue).IsAssignableFrom(e.PropertyType) && e.Name == name);
return (TValue)field?.GetValue(instance);
}
public class YourClass
{
//Add below line in your class
public object this[string propertyName] => GetType().GetProperty(propertyName)?.GetValue(this, null);
public string SampleProperty { get; set; }
}
//And you can get value of any property like this.
var value = YourClass["SampleProperty"];
짧은 길 ....
var a = new Test { Id = 1 , Name = "A" , date = DateTime.Now};
var b = new Test { Id = 1 , Name = "AXXX", date = DateTime.Now };
var compare = string.Join("",a.GetType().GetProperties().Select(x => x.GetValue(a)).ToArray())==
string.Join("",b.GetType().GetProperties().Select(x => x.GetValue(b)).ToArray());
jheddings과AlexD둘 다 속성 문자열을 해결하는 방법에 대한 훌륭한 답을 썼습니다. 그 목적을 위해 전용 라이브러리를 썼기 때문에 믹스에 내 생각을 드러내고 싶습니다.
Pather.CSharp주요 수업은Resolver
. 기본적으로 속성, 배열 및 사전 항목을 확인할 수 있습니다.
그래서, 예를 들어, 당신이이 객체를 가지고 있다면
var o = new { Property1 = new { Property2 = "value" } };
얻고 싶다.Property2
, 당신은 이렇게 할 수 있습니다 :
IResolver resolver = new Resolver();
var path = "Property1.Property2";
object result = r.Resolve(o, path);
//=> "value"
이것은 해결할 수있는 경로의 가장 기본적인 예입니다. 그것이 무엇을 할 수 있는지, 어떻게 확장 할 수 있는지 알고 싶다면,기저귀 페이지.
여기 내 해결책이있다. COM 개체에서도 작동하며 COM 개체에서 컬렉션 / 배열 항목에 액세스 할 수 있습니다.
public static object GetPropValue(this object obj, string name)
{
foreach (string part in name.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
if (type.Name == "__ComObject")
{
if (part.Contains('['))
{
string partWithoundIndex = part;
int index = ParseIndexFromPropertyName(ref partWithoundIndex);
obj = Versioned.CallByName(obj, partWithoundIndex, CallType.Get, index);
}
else
{
obj = Versioned.CallByName(obj, part, CallType.Get);
}
}
else
{
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
}
return obj;
}
private static int ParseIndexFromPropertyName(ref string name)
{
int index = -1;
int s = name.IndexOf('[') + 1;
int e = name.IndexOf(']');
if (e < s)
{
throw new ArgumentException();
}
string tmp = name.Substring(s, e - s);
index = Convert.ToInt32(tmp);
name = name.Substring(0, s - 1);
return index;
}
아래의 방법은 나를 위해 완벽하게 작동합니다.
class MyClass {
public string prop1 { set; get; }
public object this[string propertyName]
{
get { return this.GetType().GetProperty(propertyName).GetValue(this, null); }
set { this.GetType().GetProperty(propertyName).SetValue(this, value, null); }
}
}
속성 값을 가져 오려면 :
MyClass t1 = new MyClass();
...
string value = t1["prop1].ToString();
속성 값을 설정하려면 :
t1["prop1] = value;
봐.Heleonix.Reflection도서관. 경로를 기준으로 멤버를 가져 오거나 설정하거나 호출 할 수 있으며 리플렉션보다 빠른 빠른 getter / setter (델리게이트로 컴파일 된 람다)를 만들 수 있습니다. 예 :
var success = Reflector.Get(DateTime.Now, null, "Date.Year", out int value);
또는 getter를 한 번 만들고 재사용을 위해 캐시하십시오. (보다 성능이 좋지만 중간 멤버가 null 인 경우 NullReferenceException을 throw 할 수 있음)
var getter = Reflector.CreateGetter<DateTime, int>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
또는List<Action<object, object>>
다른 getter 중에서 컴파일 된 델리게이트의 기본 유형을 지정하면됩니다 (유형 변환은 컴파일 된 lambdas에 추가됩니다).
var getter = Reflector.CreateGetter<object, object>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
Employee
먼저 속성을 수정 한 다음 다시 한 번 똑같은 작업을 수행하십시오. - Ed S.public static T GetPropertyValue<T>(object obj, string propName) { return (T)obj.GetType().GetProperty(propName).GetValue(obj, null); }
- Ohad Schneider