अज्ञात वस्तु से गुण और मान प्राप्त करें


150

PHP की दुनिया से मैंने C # a go देने का फैसला किया है। मैंने एक खोज की है, लेकिन इस के बराबर कैसे करना है, इसका जवाब नहीं मिल रहा है।

$object = new Object();

$vars = get_class_vars(get_class($object));

foreach($vars as $var)
{
    doSomething($object->$var);
}

मेरे पास मूल रूप से किसी वस्तु की सूची है। ऑब्जेक्ट तीन अलग-अलग प्रकारों में से एक हो सकता है और इसमें सार्वजनिक गुणों का एक सेट होगा। मैं ऑब्जेक्ट के लिए गुणों की एक सूची प्राप्त करने में सक्षम होना चाहता हूं, उन पर लूप करें और फिर उन्हें एक फ़ाइल में लिखें। मुझे लगता है कि यह सी # प्रतिबिंब के साथ कुछ करना है, लेकिन मेरे लिए यह सब नया है।

किसी भी तरह की सहायता का स्वागत किया जाएगा।


9
एक साइड नोट के रूप में: एक सूची में विभिन्न प्रकार की वस्तुएं (एक सामान्य आधार वर्ग या इंटरफ़ेस के बिना) एक अच्छी प्रोग्रामिंग शैली नहीं है, कम से कम c # में नहीं।
एल्बिन सुन्नान्बो

जवाबों:


284

यह करना चाहिए:

Type myType = myObject.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());

foreach (PropertyInfo prop in props)
{
    object propValue = prop.GetValue(myObject, null);

    // Do something with propValue
}

PropertyInfo कहाँ से आता है?
जोनाथन

8
@jonathan System.Reflectionनाम स्थान
Cocowalla

21
वास्तव में सरणी से एक सूची बनाने की आवश्यकता नहीं है, बसPropertyInfo[] props = input.GetType().GetProperties();
व्लाद

2
क्या आप 2017 उत्तर का उपयोग करने के लिए अपडेट करना चाहते हैं Newtonsoft.Json.JsonConvert?
वायने

1
@ इसे करने का एक बिल्कुल अलग तरीका है। आपको जवाब देना चाहिए कि क्या आपको लगता है कि यह एक वैध दृष्टिकोण है
Cocowalla

23
void Test(){
    var obj = new{a="aaa", b="bbb"};

    var val_a = obj.GetValObjDy("a"); //="aaa"
    var val_b = obj.GetValObjDy("b"); //="bbb"
}
//create in a static class
static public object GetValObjDy(this object obj, string propertyName)
{            
     return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}

17

हाँ, परावर्तन जाने का रास्ता होगा। सबसे पहले, आपको वह मिलेगा Typeजो सूची में उदाहरण के प्रकार (रनटाइम पर) का प्रतिनिधित्व करता है। आप GetTypeविधि कोObject कॉल करके ऐसा कर सकते हैं । क्योंकि यह Objectवर्ग पर है, यह .NET में प्रत्येक ऑब्जेक्ट द्वारा कॉल करने योग्य है , क्योंकि सभी प्रकार से प्राप्त होते हैं Object( अच्छी तरह से, तकनीकी रूप से, सब कुछ नहीं , लेकिन यहां महत्वपूर्ण नहीं है)।

एक बार आपके पास Typeउदाहरण होने के बाद, आप उन इंस्टेंस को प्राप्त करने के लिए GetPropertiesविधि को कॉल कर सकते हैं PropertyInfoजो गुणों पर रन-टाइम जानकारी का प्रतिनिधित्व करते हैं Type

ध्यान दें, आप ओवरलोड का उपयोग करके GetPropertiesवर्गीकृत करने में मदद कर सकते हैं कि आप कौन से गुण प्राप्त करते हैं।

वहाँ से, आप बस एक फ़ाइल को जानकारी लिखेंगे।

ऊपर दिया गया आपका कोड, अनुवादित, होगा:

// The instance, it can be of any type.
object o = <some object>;

// Get the type.
Type type = o.GetType();

// Get all public instance properties.
// Use the override if you want to classify
// which properties to return.
foreach (PropertyInfo info in type.GetProperties())
{
    // Do something with the property info.
    DoSomething(info);
}

ध्यान दें कि यदि आप विधि जानकारी या क्षेत्र की जानकारी चाहते हैं, तो आपको क्रमशः GetMethodsया ओवरलोड के GetFieldsतरीकों में से एक को कॉल करना होगा ।

यह भी ध्यान दें, सदस्यों को एक फ़ाइल में सूचीबद्ध करना एक बात है, लेकिन आपको संपत्ति सेट के आधार पर तर्क ड्राइव करने के लिए इस जानकारी का उपयोग नहीं करना चाहिए

यह मानते हुए कि आपके पास प्रकारों के कार्यान्वयन पर नियंत्रण है, आपको एक सामान्य आधार वर्ग से प्राप्त करना चाहिए या एक सामान्य इंटरफ़ेस लागू करना चाहिए और उन पर कॉल करना चाहिए (आप asया isऑपरेटर का उपयोग यह निर्धारित करने में मदद करने के लिए कर सकते हैं कि आप किस आधार वर्ग / इंटरफ़ेस के साथ काम कर रहे हैं क्रम)।

हालाँकि, यदि आप इन प्रकार की परिभाषाओं को नियंत्रित नहीं करते हैं और पैटर्न मिलान के आधार पर तर्क को चलाना है, तो यह ठीक है।


11

ठीक है, सी # में यह समान है। यहां सबसे सरल उदाहरणों में से एक है (केवल सार्वजनिक संपत्तियों के लिए):

var someObject = new { .../*properties*/... };
var propertyInfos = someObject.GetType().GetProperties();
foreach (PropertyInfo pInfo in PropertyInfos)
{
    string propertyName = pInfo.Name; //gets the name of the property
    doSomething(pInfo.GetValue(someObject,null));
}

9

संपत्ति के नाम से विशिष्ट संपत्ति मूल्य प्राप्त करने के लिए

public class Bike{
public string Name {get;set;}
}

Bike b = new Bike {Name = "MyBike"};

संपत्ति के स्ट्रिंग नाम से नाम के संपत्ति मूल्य तक पहुँचने के लिए

public object GetPropertyValue(string propertyName)
{
//returns value of property Name
return this.GetType().GetProperty(propertyName).GetValue(this, null);
} 


3

Linq का उपयोग कर एक लाइन समाधान ...

var obj = new {Property1: 1, Property2: 2};
var property1 = obj.GetType().GetProperties().First(o => o.Name == "Property1").GetValue(obj , null);

2

यहाँ कुछ ऐसा है जिसे मैं एक IEnumerable<T>में बदलने के लिए उपयोग करता हूं DataTableजिसमें कॉलम शामिल हैं जो Tप्रत्येक आइटम के लिए एक पंक्ति के साथ गुणों का प्रतिनिधित्व करते हैं IEnumerable:

public static DataTable ToDataTable<T>(IEnumerable<T> items)
{
    var table = CreateDataTableForPropertiesOfType<T>();
    PropertyInfo[] piT = typeof(T).GetProperties();
    foreach (var item in items)
    {
        var dr = table.NewRow();
        for (int property = 0; property < table.Columns.Count; property++)
        {
            if (piT[property].CanRead)
            {
                var value = piT[property].GetValue(item, null);
                if (piT[property].PropertyType.IsGenericType)
                {
                    if (value == null)
                    {
                        dr[property] = DBNull.Value;
                    }
                    else
                    {
                        dr[property] = piT[property].GetValue(item, null);
                    }
                }
                else
                {
                    dr[property] = piT[property].GetValue(item, null);
                }
            }
        }
        table.Rows.Add(dr);
    }
    return table;
}

public static DataTable CreateDataTableForPropertiesOfType<T>()
{
    DataTable dt = new DataTable();
    PropertyInfo[] piT = typeof(T).GetProperties();
    foreach (PropertyInfo pi in piT)
    {
        Type propertyType = null;
        if (pi.PropertyType.IsGenericType)
        {
            propertyType = pi.PropertyType.GetGenericArguments()[0];
        }
        else
        {
            propertyType = pi.PropertyType;
        }
        DataColumn dc = new DataColumn(pi.Name, propertyType);

        if (pi.CanRead)
        {
            dt.Columns.Add(dc);
        }
    }
    return dt;
}

यह "कुछ हद तक" ओवरकम्प्लिकेटेड है, लेकिन यह देखने के लिए वास्तव में काफी अच्छा है कि परिणाम क्या है, जैसा कि आप इसे List<T>उदाहरण के लिए दे सकते हैं :

public class Car
{
    string Make { get; set; }
    int YearOfManufacture {get; set; }
}

और आपको संरचना के साथ एक DataTable लौटाया जाएगा:

बनाओ (स्ट्रिंग)
YearOfManufacture (int)

आपके प्रति आइटम में एक पंक्ति के साथ List<Car>


1

यह उदाहरण किसी ऑब्जेक्ट के सभी स्ट्रिंग गुणों को ट्रिम करता है।

public static void TrimModelProperties(Type type, object obj)
{
    var propertyInfoArray = type.GetProperties(
                                    BindingFlags.Public | 
                                    BindingFlags.Instance);
    foreach (var propertyInfo in propertyInfoArray)
    {
        var propValue = propertyInfo.GetValue(obj, null);
        if (propValue == null) 
            continue;
        if (propValue.GetType().Name == "String")
            propertyInfo.SetValue(
                             obj, 
                             ((string)propValue).Trim(), 
                             null);
    }
}

0

मुझे एप्लिकेशन ऑब्जेक्ट्स पर काम करने के लिए यह नहीं मिला है। हालाँकि मुझे इसके साथ सफलता मिली है

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();

string rval = serializer.Serialize(myAppObj);

2
यदि आप इससे बच सकते हैं, तो JavaScriptSerializer का उपयोग न करें। कई कारण हैं
नूनो एन्ड्रे

0
public Dictionary<string, string> ToDictionary(object obj)
{
    Dictionary<string, string> dictionary = new Dictionary<string, string>();

    Type objectType = obj.GetType();
    IList<PropertyInfo> props = new List<PropertyInfo>(objectType.GetProperties());

    foreach (PropertyInfo prop in props)
    {
        object propValue = prop.GetValue(obj, null);
        dictionary.Add(prop.Name, propValue.ToString());
    }

    return dictionary;
}

0
    /// get set value field in object to object new (two object  field like ) 

    public static void SetValueObjectToObject (object sourceObj , object resultObj)
    {
        IList<PropertyInfo> props = new List<PropertyInfo>(sourceObj.GetType().GetProperties());
        foreach (PropertyInfo prop in props)
        {
            try
            {
                //get value in sourceObj
                object propValue = prop.GetValue(sourceObj, null);
                //set value in resultObj
                PropertyInfo propResult = resultObj.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance);
                if (propResult != null && propResult.CanWrite)
                {
                    propResult.SetValue(resultObj, propValue, null);
                }
            }
            catch (Exception ex)
            {  
                // do something with Ex
            }
        }
    }

-1

आप यह कोशिश कर सकते हैं:

string[] arr = ((IEnumerable)obj).Cast<object>()
                                 .Select(x => x.ToString())
                                 .ToArray();

एक बार प्रत्येक सरणी IEnumerable इंटरफ़ेस को लागू करता है

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