C # में प्रतिबिंब का उपयोग करके स्ट्रिंग से संपत्ति का मूल्य प्राप्त करें


928

मैं अपने कोड में प्रतिबिंब 1 उदाहरण का उपयोग करके डेटा परिवर्तन को लागू करने का प्रयास कर रहा हूं।

GetSourceValueसमारोह एक स्विच विभिन्न प्रकार की तुलना की है, लेकिन मैं इन प्रकार के और गुण को हटाने और करना चाहते GetSourceValueसंपत्ति पैरामीटर के रूप में केवल एक ही स्ट्रिंग का उपयोग कर के मूल्य मिलता है। मैं एक वर्ग और संपत्ति को स्ट्रिंग में पास करना चाहता हूं और संपत्ति के मूल्य को हल करना चाहता हूं।

क्या यह संभव है?

मूल ब्लॉग पोस्ट का 1 वेब आर्काइव संस्करण

जवाबों:


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

बेशक, आप सत्यापन और व्हाट्सएप जोड़ना चाहते हैं, लेकिन यह इसका सार है।


8
अच्छा और सरल! मैं इसे सामान्य बना देता हूँ:public static T GetPropertyValue<T>(object obj, string propName) { return (T)obj.GetType().GetProperty(propName).GetValue(obj, null); }
ओहद श्नाइडर

2
एक अनुकूलन इस तरह के अशक्त अपवाद के जोखिम को दूर कर सकता है: " src.GetType().GetProperty(propName)?.GetValue(src, null);";)।
shA.t

8
@ shA.t: मुझे लगता है कि यह एक बुरा विचार है। आप किसी मौजूदा संपत्ति के शून्य मान या किसी संपत्ति के बीच अंतर कैसे करते हैं? मुझे तुरंत पता होगा कि मैं एक खराब संपत्ति के नाम पर भेज रहा हूं। यह उत्पादन कोड नहीं है, लेकिन एक बेहतर सुधार एक अधिक विशिष्ट अपवाद को फेंकना होगा (उदाहरण के लिए नल की जांच करें GetPropertyऔर फेंक दें PropertyNotFoundExceptionया यदि शून्य हो।)
एड एस।

210

इस जैसे किसी और के बारे में क्या राय है:

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

आप या तो इन विधियों का उपयोग स्थैतिक विधियों या एक्सटेंशन के रूप में कर सकते हैं।


3
@FredJand खुशी है कि आप उस पर ठोकर खाई! जब ये पुराने पोस्ट चालू होते हैं तो हमेशा आश्चर्य होता है। यह थोड़ा अस्पष्ट था इसलिए मैंने इसे समझाने के लिए थोड़ा सा पाठ जोड़ा। मैंने इन्हें विस्तार विधियों के रूप में उपयोग करने के लिए स्विच किया है और एक जेनरिक फ़ॉर्म जोड़ा है, इसलिए मैंने इसे यहां जोड़ा।
jheddings

फ़ॉरेस्ट में नल गार्ड क्यों है और ऊपर नहीं है?
संथोस

4
@ सैंटोस चूंकि 'ऑबज' को फॉर्फ़ लूप के शरीर में पुनर्परिभाषित किया गया है, इसलिए इसे प्रत्येक पुनरावृत्ति के दौरान जांचा जाता है।
झेजिंग्स

उपयोगी, लेकिन किनारे के मामले में कि नेस्टेड गुणों में से एक को छिपाया जा सकता है ('नए' संशोधक का उपयोग करके), यह डुप्लिकेट गुण खोजने के लिए एक अपवाद फेंक देगा। यह अंतिम संपत्ति प्रकार पर नज़र रखने और नेस्टेड गुणों के PropertyInfo.PropertyTypeबजाय उपयोग करने के लिए obj.GetType(), ठीक उसी तरह से होगा जैसे कि एक नेस्टेड संपत्ति पर संपत्ति का उपयोग करना होगा।
नुलियस

आप nameofइस तरह C # 6 के रूप में अभिव्यक्ति का उपयोग कर सकते हैं : nameof(TimeOfDay.Minutes)नाम पैरामीटर पर जब मैजिक स्ट्रिंग्स से छुटकारा पाने के लिए फ़ंक्शन को कॉल करते हैं और इन कॉलों के लिए संकलन समय सुरक्षा जोड़ते हैं।
रीप

74

किसी में जोड़ें 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"];

@EduardoCuomo: क्या इस के साथ प्रतिबिंब का उपयोग करना संभव है इसलिए आपको यह जानने की आवश्यकता नहीं है कि कक्षा के सदस्यों के पास क्या है?
हमारा आदमी केले में

यदि "बार" एक वस्तु थे तो क्या ऐसा करना संभव है?
बड़ा_वाटर

@big_water SetValueऔर GetValueतरीके के साथ काम करता है Object। यदि आपको एक विशिष्ट प्रकार के साथ काम करने की आवश्यकता है, तो आपको परिणाम देना चाहिए GetValueऔर इसके साथ असाइन करने के लिए मूल्य डालना चाहिएSetValue
Eduardo Cuomo

क्षमा करें @OurManinBananas, मैं आपके प्रश्न को नहीं समझ सकता। आप क्या करना चाहते हैं?
एडुआर्डो कुओमो

इस प्रकार के तरीकों का नाम क्या है ..?
सहान चिन्तक

45

क्या उपयोग करने के बारे CallByNameमें Microsoft.VisualBasicनाम स्थान ( Microsoft.VisualBasic.dll)? यह सामान्य वस्तुओं, COM ऑब्जेक्ट्स, और यहां तक ​​कि डायनामिक ऑब्जेक्ट्स के गुण, फ़ील्ड और तरीके प्राप्त करने के लिए प्रतिबिंब का उपयोग करता है।

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

और फिर

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

5
दिलचस्प सुझाव, आगे के निरीक्षण ने साबित किया कि यह दोनों फ़ील्ड और गुण, COM ऑब्जेक्ट्स को संभाल सकता है , और यह सही ढंग से गतिशील बंधन को भी संभाल सकता है !
IllidanS4 मोनिका को

मुझे एक त्रुटि मिल रही है: टाइप 'MyType' पर सार्वजनिक सदस्य 'MyPropertyName' नहीं मिला।
vldmrrdjcc

30

झेजिंग द्वारा शानदार जवाब। मैं इसे समग्र सरणियों या वस्तुओं के संग्रह की संदर्भित करने की अनुमति देना चाहता हूं, ताकि प्रॉपर्टीनामे 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;
    }

मास्टरलिस्ट द्वारा एक्सेस की गई सूचियों की सूची [0] [1] के बारे में क्या?
जेसी एडम

Array के रूप में -> as object [] भी Nullreference अपवाद में होता है। मेरे लिए क्या काम करता है (सबसे कुशल विधि नहीं है), परिणाम पर अज्ञात त्रुटि का उपयोग करने के लिए और परिणाम पर ToArray () का उपयोग करना है। fiddle
जीरोन जोंकमैन

14

यदि मैं Ed S. से प्राप्त कोड का उपयोग करता हूं

'ReflectionExtensions.GetProperty (टाइप, स्ट्रिंग)' अपने सुरक्षा स्तर के कारण दुर्गम है

ऐसा लगता है कि GetProperty()Xamarin में उपलब्ध नहीं है। कीड़े। TargetFrameworkProfileहैProfile7 मेरी पोर्टेबल कक्षा लाइब्रेरी (.NET फ्रेमवर्क 4.5, Windows 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);
}

स्रोत


4
बस एक छोटा सा सुधार। IF और अगली रिटर्न को बदलें: रिटर्न प्रॉपर्टी; .GetValue (स्रोत);
टोमिनो

11

नेस्टेड गुण चर्चा के बारे में, यदि आप DataBinder.Eval Method (Object, String)नीचे दिए गए उपयोग करते हैं, तो आप सभी प्रतिबिंब सामग्री से बच सकते हैं:

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

बेशक, आपको System.Webविधानसभा में एक संदर्भ जोड़ना होगा , लेकिन यह शायद एक बड़ी बात नहीं है।


8

कॉल करने की विधि .NET मानक (1.6 के रूप में) में बदल गई है। इसके अलावा, हम C # 6 के शून्य सशर्त ऑपरेटर का उपयोग कर सकते हैं।

using System.Reflection; 
public static object GetPropValue(object src, string propName)
{
    return src.GetType().GetRuntimeProperty(propName)?.GetValue(src);
}

1
उपयोग करने के लिए? operator
9

4

System.Reflection namespace के PropertyInfo का उपयोग करना । परावर्तन ठीक ही संकलित करता है, चाहे हम कितनी भी संपत्ति तक पहुँचने की कोशिश करें। रन-टाइम के दौरान त्रुटि सामने आएगी।

    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 भी लौटा सकते हैं।


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

यह एक सूची में सभी गुणों को उनके मूल्यों के साथ प्राप्त करने का एक तरीका है।


ऐसा क्यों कर रहे हैं: type.GetProperty(pi.Name)जब चर के लिए == है pi?
पश्चिम जयन

यदि आप c # 6.0 का उपयोग कर रहे हैं, तो छुटकारा पाएं ifऔर selfValue?.ToString()अन्यथा से छुटकारा पाएं ifऔर उपयोग करेंselfValue==null?null:selfValue.ToString()
weston

इसके अलावा List<KeyValuePair<, अजीब की एक सूची है, एक शब्दकोष का उपयोग करेंDictionary<string, string>
पश्चिम

3

निम्नलिखित कोड एक वस्तु के उदाहरण में निहित सभी संपत्ति नामों और मूल्यों के पूरे पदानुक्रम को प्रदर्शित करने के लिए एक पुनरावर्ती विधि है। यह विधि GetPropertyValue()इस धागे में ऊपर एलेक्सडी के उत्तर के सरलीकृत संस्करण का उपयोग करती है । इस चर्चा सूत्र के लिए धन्यवाद, मैं यह पता लगाने में सक्षम था कि यह कैसे करना है!

उदाहरण के लिए, मैं इस विधि का उपयोग किसी 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);
    }
  }
}

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

3
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"];

3

नीचे दी गई विधि मेरे लिए एकदम सही है:

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;

2
Dim NewHandle As YourType = CType(Microsoft.VisualBasic.CallByName(ObjectThatContainsYourVariable, "YourVariableName", CallType), YourType)

2

यहां एक नेस्टेड प्रॉपर्टी खोजने का एक और तरीका है जिसमें आपको नेस्टिंग रास्ता बताने के लिए स्ट्रिंग की आवश्यकता नहीं है। एकल संपत्ति विधि के लिए एड एस को क्रेडिट।

    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रिटर्न और एक लूप में फेंक दिया गया है। nullGetValueNullReferenceException
ग्रो

2

आप कभी भी इस बात का उल्लेख नहीं करते हैं कि आप किस वस्तु का निरीक्षण कर रहे हैं, और चूंकि आप किसी दिए गए ऑब्जेक्ट को संदर्भित करने वाले लोगों को अस्वीकार कर रहे हैं, इसलिए मैं मान लूंगा कि आपका मतलब स्थिर है।

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

ध्यान दें कि मैंने उस वस्तु को चिह्नित किया है जिसका स्थानीय चर के साथ निरीक्षण किया जा रहा है objnullस्थैतिक का मतलब है, अन्यथा आप जो चाहते हैं उसे सेट करें। यह भी ध्यान दें कि GetEntryAssembly()"रनिंग" असेंबली प्राप्त करने के लिए कुछ उपलब्ध तरीकों में से एक है, यदि आप हार्ड लोडिंग टाइप कर रहे हैं तो आप इसके साथ खेलना चाहते हैं।


2

हेलेओनिक्स.रिफ्लेक्शन लाइब्रेरी पर एक नज़र । आप पथ द्वारा सदस्यों को प्राप्त / सेट / इनवॉइस कर सकते हैं, या एक गेटटर / सेटर (एक प्रतिनिधि में संकलित लैम्ब्डा) बना सकते हैं जो प्रतिबिंब से तेज है। उदाहरण के लिए:

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

या एक बार एक गेटर बनाएं और पुनः उपयोग के लिए कैश करें (यह अधिक परफॉर्मेंट है लेकिन NullReferenceException को फेंक सकता है यदि एक मध्यवर्ती सदस्य शून्य है):

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

या यदि आप List<Action<object, object>>अलग-अलग गेटर्स बनाना चाहते हैं , तो संकलित प्रतिनिधियों के लिए बस आधार प्रकार निर्दिष्ट करें (संकलित लंबोदर में रूपांतरण जोड़ा जाएगा):

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

1
कभी भी 3 पार्टी लिबास का उपयोग न करें, यदि आप इसे 5-10 पंक्तियों में उचित समय में अपने कोड में लागू कर सकते हैं।
Artem G

1

छोटा रास्ता…।

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

jhgings और 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"

यह उन रास्तों का सबसे बुनियादी उदाहरण है जो इसे हल कर सकते हैं। यदि आप यह देखना चाहते हैं कि यह और क्या कर सकता है, या आप इसे कैसे आगे बढ़ा सकते हैं, तो इसके जीथूब पेज पर जाएं


0

यहाँ मेरा समाधान है। यह 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;
}

0

यहां मुझे अन्य उत्तरों के आधार पर मिला है। त्रुटि से निपटने के साथ इतना विशिष्ट होने पर थोड़ा ओवरकिल।

public static T GetPropertyValue<T>(object sourceInstance, string targetPropertyName, bool throwExceptionIfNotExists = false)
{
    string errorMsg = null;

    try
    {
        if (sourceInstance == null || string.IsNullOrWhiteSpace(targetPropertyName))
        {
            errorMsg = $"Source object is null or property name is null or whitespace. '{targetPropertyName}'";
            Log.Warn(errorMsg);

            if (throwExceptionIfNotExists)
                throw new ArgumentException(errorMsg);
            else
                return default(T);
        }

        Type returnType = typeof(T);
        Type sourceType = sourceInstance.GetType();

        PropertyInfo propertyInfo = sourceType.GetProperty(targetPropertyName, returnType);
        if (propertyInfo == null)
        {
            errorMsg = $"Property name '{targetPropertyName}' of type '{returnType}' not found for source object of type '{sourceType}'";
            Log.Warn(errorMsg);

            if (throwExceptionIfNotExists)
                throw new ArgumentException(errorMsg);
            else
                return default(T);
        }

        return (T)propertyInfo.GetValue(sourceInstance, null);
    }
    catch(Exception ex)
    {
        errorMsg = $"Problem getting property name '{targetPropertyName}' from source instance.";
        Log.Error(errorMsg, ex);

        if (throwExceptionIfNotExists)
            throw;
    }

    return default(T);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.