Get property value from string using reflection in C#
Próbuję zaimplementować transformację danych za pomocą odbicia1 przykład w moim kodzie.
Funkcja GetSourceValue
mA przełącznik porównujący różne typy, ale chcę usunąć te typy i właściwości i mieć GetSourceValue
uzyskać wartość właściwości używając tylko jednego ciągu jako parametru. Chcę przekazać klasę i właściwość w łańcuchu i rozwiązać wartość właściwości.
21 answers
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
Oczywiście będziesz chciał dodać walidację i takie tam, ale w tym tkwi sedno sprawy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-03 23:12:20
A może coś takiego:
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;
}
To pozwoli Ci zejść do właściwości za pomocą pojedynczego ciągu znaków, jak to:
DateTime now = DateTime.Now;
int min = GetPropValue<int>(now, "TimeOfDay.Minutes");
int hrs = now.GetPropValue<int>("TimeOfDay.Hours");
Możesz użyć tych metod jako metod statycznych lub rozszerzeń.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-08 15:23:00
Dodaj do dowolnego 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; }
}
Następnie możesz użyć jako:
Foo f = new Foo();
// Set
f["Bar"] = "asdf";
// Get
string s = (string)f["Bar"];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-23 19:58:10
A co z użyciem CallByName
z Microsoft.VisualBasic
przestrzeni nazw (Microsoft.VisualBasic.dll
)? Wykorzystuje odbicie, aby uzyskać właściwości, pola i metody normalnych obiektów, Obiektów COM, a nawet obiektów dynamicznych.
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
A następnie
Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString();
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-02 18:04:26
Świetna odpowiedź jheddingsa. Chciałbym go ulepszyć, pozwalając na odwoływanie się do zagregowanych tablic lub kolekcji obiektów, tak aby propertyName mógł być 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-02 21:53:53
Jeśli użyję kodu z Ed s. otrzymuję
'ReflectionExtensions.GetProperty( Type, string) ' jest niedostępne ze względu na poziom ochrony
Wydaje się, że {[1] } nie jest dostępny w Xamarin.Formularze. TargetFrameworkProfile
jest Profile7
w mojej przenośnej bibliotece klas (. NET Framework 4.5, Windows 8, ASP.NET Core 1.0, Xamarin.Android, Xamarin.iOS, Xamarin.iOS Classic).
Teraz znalazłem rozwiązanie pracy:
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 10:18:44
Jeśli chodzi o omówienie właściwości zagnieżdżonych, możesz uniknąć wszystkich rzeczy refleksji, jeśli użyjesz DataBinder.Eval Method (Object, String)
Jak poniżej:
var value = DataBinder.Eval(DateTime.Now, "TimeOfDay.Hours");
Oczywiście, musisz dodać odniesienie do Zgromadzenia System.Web
, ale to prawdopodobnie nie jest wielka sprawa.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-29 14:19:48
Korzystanie z PropertyInfo systemu .Reflection przestrzeń nazw. Reflection kompiluje się bez względu na to, do jakiej własności chcemy uzyskać dostęp. Błąd pojawi się podczas uruchamiania.
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;
}
Działa dobrze, aby uzyskać Właściwość Location obiektu
Label1.Text = GetObjProperty(button1, "Location").ToString();
Otrzymamy lokalizację: {X = 71, Y=27} Możemy również zwrócić lokalizację.X lub lokalizacja.W ten sam sposób.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 14:47:22
Metoda wywołania została zmieniona w. NET Standard (od 1.6). Możemy również użyć operatora warunkowego null W C # 6.
using System.Reflection;
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetRuntimeProperty(propName)?.GetValue(src);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-25 09:13:23
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;
}
Jest to sposób, aby uzyskać wszystkie właściwości z ich wartościami na liście.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-06 13:46:24
Oto inny sposób na znalezienie zagnieżdżonej właściwości, która nie wymaga łańcucha znaków, aby podać ścieżkę zagnieżdżenia. Kredyt dla Ed S. na jedną nieruchomość.
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-05 00:38:13
Nigdy nie wspominasz, jaki obiekt badasz, a ponieważ odrzucasz te, które odnoszą się do danego obiektu, zakładam, że masz na myśli statyczny.
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);
}
Zauważ, że zaznaczyłem obiekt, który jest sprawdzany zmienną lokalną obj
. null
oznacza statyczny, w przeciwnym razie ustaw go na to, co chcesz. Zauważ również, że GetEntryAssembly()
jest jedną z kilku dostępnych metod uzyskania "uruchomionego" zestawu, możesz chcieć się nim pobawić, jeśli masz trudności z załadowaniem tego typu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 08:56:27
Poniższy kod jest rekurencyjną metodą wyświetlania całej hierarchii wszystkich nazw właściwości i wartości zawartych w instancji obiektu. Ta metoda wykorzystuje uproszczoną wersję odpowiedzi AlexD GetPropertyValue()
powyżej w tym wątku. Dzięki temu wątkowi dyskusyjnemu udało mi się dowiedzieć, jak to zrobić!
Na przykład, używam tej metody, aby pokazać eksplozję lub zrzut wszystkich właściwości w odpowiedzi WebService
, wywołując metodę w następujący sposób:
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);
}
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 08:56:58
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"];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-06 15:06:15
Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-30 23:55:28
Krótsza droga ....
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());
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-13 04:34:29
Jheddings i AlexD napisali doskonałe odpowiedzi na temat rozwiązywania łańcuchów właściwości. Chciałbym dorzucić swoją do miksu, ponieważ napisałem dedykowaną bibliotekę właśnie w tym celu.
Pather.CSharp'główna klasa S to Resolver
. Domyślnie może rozwiązywać właściwości, tablice i wpisy słownika.
Więc, na przykład, jeśli masz taki obiekt
var o = new { Property1 = new { Property2 = "value" } };
I chcesz dostać Property2
, możesz to zrobić tak:
IResolver resolver = new Resolver();
var path = "Property1.Property2";
object result = r.Resolve(o, path);
//=> "value"
To jest najbardziej podstawowy przykład ścieżek, które może rozwiązać. Jeśli chcesz zobaczyć, co jeszcze może, lub jak możesz go rozszerzyć, po prostu przejdź do strony Github .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:26
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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-29 16:22:41
Oto moje rozwiązanie. Działa również z obiektami COM i umożliwia dostęp do elementów kolekcji/tablicy z obiektów 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-24 14:24:34
Poniższa metoda działa dla mnie idealnie:
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); }
}
}
Aby uzyskać wartość właściwości:
MyClass t1 = new MyClass();
...
string value = t1["prop1].ToString();
Aby ustawić wartość właściwości:
t1["prop1] = value;
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-09 05:19:07
Spójrz na Helionix.Reflection library. Możesz uzyskać/set/invoke członków za pomocą ścieżek, lub utworzyć getter / setter (lambda skompilowany do delegata), który jest szybszy niż odbicie. Na przykład:
var success = Reflector.Get(DateTime.Now, null, "Date.Year", out int value);
Lub utworzyć getter raz i bufor do ponownego użycia (jest to bardziej wydajne, ale może rzucić Nullreferencexception, jeśli pośredni element jest null):
var getter = Reflector.CreateGetter<DateTime, int>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
Lub jeśli chcesz utworzyć List<Action<object, object>>
różnych getterów, po prostu określ typy bazowe dla skompilowanych delegatów (konwersje typu będą dodawane do skompilowanych lambd):
var getter = Reflector.CreateGetter<object, object>("Date.Year", typeof(DateTime));
getter(DateTime.Now);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-13 10:57:55