Gauti nuosavybės vertę iš eilutės naudodami atspindį C #

Bandau įdiegti duomenų transformaciją, naudodamas savo kodą 1 atspindį.

Funkcija GetSourceValue turi jungiklį, kuris lygina skirtingus tipus, bet noriu pašalinti šiuos tipus ir savybes ir GetSourceValue kad gautumėte turto vertę, naudojant tik vieną eilutę kaip parametrą. Noriu perduoti klasę ir turtą eilutėje ir išspręsti nuosavybės vertę

Ar tai įmanoma?

1 Pradinio dienoraščio žiniatinklio archyvo versija

702
29 июля '09 в 0:58 2009-07-29 00:58 pedrofernandes yra nustatytas liepos 29 d ., 09:58, 2009-07-29 00:58
ответ 21 atsakymas
  public static object GetPropValue(object src, string propName) { return src.GetType().GetProperty(propName).GetValue(src, null); } 

Žinoma, norite pridėti patvirtinimą ir kažką kitą, tačiau tai yra jos esmė.

1401
29 июля '09 в 1:02 2009-07-29 01:02 atsakymą pateikė Ed S. liepos 29 d. '09, 1:02 2009-07-29 01:02

Kaip apie kažką panašaus:

 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; } 

Tai leis jums pereiti prie savybių su viena eilute, pavyzdžiui:

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

Šiuos metodus galite naudoti kaip statinius metodus ar plėtinius.

176
23 дек. „ Jheddings“ atsakymas gruodžio 23 d 2009-12-23 21:55 '09 ne 9:55 PM 2009-12-23 21:55

Pridėti prie bet kurios 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; } } 

Tada galite naudoti abu:

 Foo f = new Foo(); // Set f["Bar"] = "asdf"; // Get string s = (string)f["Bar"]; 
47
23 июля '14 в 22:58 2014-07-23 22:58 atsakymą pateikė Eduardo Cuomo , liepos 23 d. 14, 22:58 2014-07-23 22:58

Kaip apie „ CallByName Microsoft.VisualBasic vardų CallByName ( Microsoft.VisualBasic.dll )? Jis naudoja atspindžius, kad gautų paprastų objektų, COM objektų ir net dinaminių objektų savybes, laukus ir metodus.

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

ir tada

 Versioned.CallByName(this, "method/function/prop name", CallType.Get).ToString(); 
40
23 дек. Atsakymą pateikė Fredou, gruodžio 23 d. 2009-12-23 22:24 '09 10:24 val. 2009-12-23 22:24

Puikus atsakymas į antraštes. Norėčiau ją patobulinti, leisdama jums apibendrinti apibendrintas matricas ar objektų rinkinius, todėl nuosavybės pavadinimas gali būti nuosavybė1.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; } 
23
14 февр. atsakymas pateikiamas AlexD 14 vasario mėn . 2012-02-14 12:18 '12 12:18 2012-02-14 12:18

Jei aš naudoju kodą iš Ed S., aš gaunu

„ReflectionExtensions.GetProperty“ (tipas, eilutė) nėra prieinama dėl apsaugos lygio

Atrodo, kad „ GetProperty() nėra Xamarin.Forms. TargetFrameworkProfile yra Profile7 mano nešiojamų klasių bibliotekoje (.NET Framework 4.5, Windows 8, ASP.NET Core 1.0, Xamarin.Android, Xamarin.iOS, Xamarin.iOS Classic).

Dabar radau darbo sprendimą:

 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); } 

Šaltinis

8
06 сент. atsakymas buvo išbandytas 06.09. 2016-09-06 12:18 '16 at 12:18 pm 2016-09-06 12:18

Apie aptariamų savybių aptarimą galite išvengti visų apmąstymų, jei naudojate „ DataBinder.Eval Method (Object, String) kaip parodyta toliau:

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

Žinoma, jums reikia pridėti nuorodą į „ System.Web surinkimą, tačiau tai tikriausiai nėra didelis dalykas.

6
29 июля '15 в 17:19 2015-07-29 17:19 atsakymą pateikė Rubensas Fariasas, liepos 29 d. 15, 17:19 2015-07-29 17:19

Naudokite „PropertyInfo“ sistemoje. Refleksija yra sukaupta tik gerai, nesvarbu, kokio turto mes bandome gauti. Klaida pasirodys vykdymo metu.

  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; } 

Tai puikiai veikia, jei norite gauti objekto vietą.

 Label1.Text = GetObjProperty(button1, "Location").ToString(); 

Mes gauname vietą: {X = 71, Y = 27} Taip pat galime grąžinti vietą.X arba vietą.

4
04 нояб. atsakymą pateikė A Ghazal 04.11 . 2013-11-04 09:06 '13, 9:06, 2013-11-04 09:06

Pokalbio metodas pasikeitė .NET standarte (nuo 1.6 versijos). Taip pat galime naudoti sąlyginį operatoriaus operatorių C # 6.

 using System.Reflection; public static object GetPropValue(object src, string propName) { return src.GetType().GetRuntimeProperty(propName)?.GetValue(src); } 
4
24 мая '17 в 18:06 2017-05-24 18:06 atsakymą pateikė Mattas Frearas gegužės 24 d., 17: 06: 00-24 18:06
 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; } 

Tai būdas gauti visas savybes sąraše su jų vertybėmis.

3
06 янв. Atsakymas duotas Boncho Vlkov 06 Jan 2016-01-06 16:46 '16 at 16:46 2016-01-06 16:46

Čia yra dar vienas būdas rasti pridėtą savybę, kuriai nereikia eilutės, rodančios lizdą. Gauti „Ed S.“ dėl vieno savybės metodo.

  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); } 
2
05 нояб. atsakymas duotas Recursor 05 Nov. 2014-11-05 03:15 '14 at 3:15 2014-11-05 03:15

Niekada neminote, kokio objekto jūs tikrinate, ir kadangi jūs atmetate tuos, kurie nurodo šį objektą, manau, kad tai reiškia statinį.

 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); } 

Atkreipkite dėmesį, kad pažymėjau objektą, kuris tikrinamas su vietiniu kintamuoju obj . null reiškia statinį, kitaip nustatydamas tai, ko norite. Taip pat atkreipkite dėmesį, kad „ GetEntryAssembly() yra vienas iš kelių būdų, kaip gauti „veikiančią“ sąranką, galbūt norėsite žaisti su juo, jei sunkiai įkeliate šį tipą.

2
23 дек. atsakymas, kurį pateikė Guvante . 2009-12-23 22:13 '09 10:13 val. 2009-12-23 22:13

Šis kodas yra rekursinis metodas, rodantis visą visų vardų hierarchiją. Objektų egzemplioriuje esantys vardai ir vertės. Šis metodas naudoja supaprastintą „AlexD GetPropertyValue() atsakymo versiją šiame sraute. Dėl šios diskusijos temos galėjau išsiaiškinti, kaip tai padaryti!

Pvz., Naudoju šį metodą, norint rodyti „ WebService atsakyme WebService arba visų savybių sąvartyną, vadindamas šį metodą:

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 namespace path. // Recursion extends this to be the property full namespace path. string currentPath = parentPath + "." + pi.Name; // Get the selected property 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); } } } 
2
26 февр. atsakymą pateikė gridtrak 26 vasaris 2015-02-26 05:04 '15, 5:04 am 2015-02-26 05:04
 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"]; 
2
06 марта '18 в 18:06 2018-03-06 18:06 Atsakymą pateikė Komal Narang kovo 06-18 d. 18:06 2018-03-06 18:06

trumpesnis būdas ....

 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()); 
1
13 июля '14 в 7:11 2014-07-13 07:11 atsakymas duotas Budiantowang liepos 13 d. 14 val

Jeddings ir AlexD yra puikūs atsakymai į klausimą, kaip išspręsti nuosavybės eilutes. Norėčiau mesti mano mišinį, nes tam tikslui parašiau specialią biblioteką.

Pather.CSharp pagrindinė klasė Resolver . Pagal numatytuosius nustatymus jis gali leisti naudoti nuosavybės, masyvo ir žodyno įrašus.

Taigi, pavyzdžiui, jei turite tokį objektą

 var o = new { Property1 = new { Property2 = "value" } }; 

ir norite gauti Property2 , galite tai padaryti taip:

 IResolver resolver = new Resolver(); var path = "Property1.Property2"; object result = r.Resolve(o, path); //=> "value" 

Tai paprasčiausias būdų, kaip jis gali išspręsti, pavyzdys. Jei norite pamatyti, ką dar jis gali, arba kaip galite ją išplėsti, eikite į „ Github“ puslapį.

1
27 авг. atsakymą pateikė Domysee 27 rug . 2016-08-27 00:48 '16 at 0:48 2016-08-27 00:48
 Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType) 
1
14 июня '10 в 0:12 2010-06-14 00:12 atsakymą Kyle pateikė birželio 14 d. 10 val. 0:12 2010-06-14 00:12
 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); } 
1
29 сент. atsakymą pateikė Rahma Sammaron 29 sep . 2017-09-29 19:22 '17, 19:22 pm 2017-09-29 19:22

Toliau pateiktas metodas puikiai tinka man:

 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); } } } 

Jei norite gauti turto vertę:

 MyClass t1 = new MyClass(); ... string value = t1["prop1].ToString(); 

Jei norite nustatyti turto vertę:

 t1["prop1] = value; 
0
09 июля '18 в 8:19 2018-07-09 08:19 atsakymas duotas Derrick.X liepos 09-18 d. 8:19. 2018-07-09 08:19

Žr.Heleonix“ . Jūs galite gauti / nustatyti / skambinti narius keliais arba sukurti getter / setter (lambda, sudarytą į delegatą), kuris yra greitesnis nei refleksija. Pavyzdžiui:

 var success = Reflector.Get(DateTime.Now, null, "Date.Year", out int value); 

Arba vieną kartą sukurkite „getter“ ir pakartotinai naudokite talpyklą (tai yra veiksmingesnė, tačiau gali sukelti „NullReferenceException“ išimtį, jei tarpinis terminas yra nulis):

 var getter = Reflector.CreateGetter<DateTime, int>("Date.Year", typeof(DateTime)); getter(DateTime.Now); 

Arba, jei norite sukurti List<Action<object, object>> skirtingų autorių List<Action<object, object>> , tiesiog nurodykite sukauptų delegatų bazinius tipus (konversijų tipai bus įtraukti į sukurtus lambdas):

 var getter = Reflector.CreateGetter<object, object>("Date.Year", typeof(DateTime)); getter(DateTime.Now); 
0
13 июля '18 в 13:57 2018-07-13 13:57 atsakymą pateikė Hennadii Lutsyshyn liepos 13 d. 18 val. 13:57

Čia yra mano sprendimas. Jis taip pat veikia su COM objektais ir leidžia pasiekti COM rinkinių kolekcijos / masyvo elementus.

 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; } 
0
24 февр. Atsakymą pateikė vartotojo3175253 vasario 24 d. 2018-02-24 17:24 '18 at 17:24 pm 2018-02-24 17:24

Kiti klausimai apie žymės arba Užduoti klausimą