Dapatkan properti dan nilai dari objek yang tidak dikenal


150

Dari dunia PHP saya telah memutuskan untuk mencoba C #. Saya sudah mencari tetapi tampaknya tidak dapat menemukan jawaban tentang bagaimana melakukan yang setara dengan ini.

$object = new Object();

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

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

Saya pada dasarnya memiliki Daftar objek. Objek bisa menjadi salah satu dari tiga jenis yang berbeda dan akan memiliki seperangkat properti publik. Saya ingin bisa mendapatkan daftar properti untuk objek, mengulanginya dan kemudian menuliskannya ke file. Saya pikir ini ada hubungannya dengan c # reflection tetapi itu semua baru bagi saya.

Bantuan apa pun akan sangat dihargai.


9
Sebagai catatan: memiliki objek dari berbagai jenis dalam daftar (tanpa kelas dasar umum atau antarmuka) bukan gaya pemrograman yang baik, setidaknya tidak dalam c #.
Albin Sunnanbo

Jawaban:


284

Ini harus dilakukan:

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
}

dari mana datangnya PropertyInfo?
Jonathan dos Santos

8
@jonathan System.Reflectionnamespace
Cocowalla

21
Tidak perlu benar-benar membuat daftar dari array, cukup PropertyInfo[] props = input.GetType().GetProperties();
VladL

2
Apakah Anda ingin memperbarui untuk jawaban 2017 menggunakan Newtonsoft.Json.JsonConvert?
Vayne

1
@ clone itu cara yang sangat berbeda untuk melakukannya. Anda harus memposting jawaban jika Anda pikir itu pendekatan yang valid
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

Ya, Refleksi akan menjadi cara untuk pergi. Pertama, Anda akan mendapatkanType yang mewakili tipe (saat runtime) dari instance dalam daftar. Anda dapat melakukan ini dengan memanggil GetTypemetodeObject . Karena ada di Objectkelas, itu bisa dipanggil oleh setiap objek di .NET, karena semua jenis berasal dari Object( well, secara teknis, bukan segalanya , tapi itu tidak penting di sini).

Setelah Anda memiliki Typeinstance, Anda dapat memanggil GetPropertiesmetode untuk mendapatkan PropertyInfoinstance yang mewakili informasi run-timea tentang properti diType .

Catatan, Anda dapat menggunakan kelebihan GetPropertiesuntuk membantu mengklasifikasikan mana sifat Anda mengambil.

Dari sana, Anda hanya akan menulis informasi ke file.

Kode Anda di atas, diterjemahkan, akan menjadi:

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

Perhatikan bahwa jika Anda menginginkan informasi metode atau informasi bidang, Anda harus memanggil salah satu dari kelebihan GetMethods atau GetFieldsmetode masing-masing.

Juga perhatikan, itu satu hal untuk daftar anggota ke file, tetapi Anda tidak harus menggunakan informasi ini untuk mendorong logika berdasarkan set properti.

Dengan asumsi Anda memiliki kontrol atas implementasi tipe, Anda harus berasal dari kelas dasar umum atau mengimplementasikan antarmuka umum dan membuat panggilan pada mereka (Anda dapat menggunakan as atauis operator untuk membantu menentukan kelas dasar / antarmuka mana Anda bekerja dengan di runtime).

Namun, jika Anda tidak mengontrol definisi tipe ini dan harus menggerakkan logika berdasarkan pencocokan pola, maka itu tidak masalah.


11

baik, di C # itu mirip. Berikut adalah salah satu contoh paling sederhana (hanya untuk properti publik):

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

Untuk mendapatkan nilai properti spesifik dari nama properti

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

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

untuk mengakses nilai properti Name dari string name of property

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

3

Anda dapat menggunakan GetType - GetProperties - Linq Foreach :

obj.GetType().GetProperties().ToList().ForEach(p =>{
                                                        //p is each PropertyInfo
                                                        DoSomething(p);
                                                    });

3

Satu solusi garis menggunakan Linq ...

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

2

Berikut ini sesuatu yang saya gunakan untuk mengubah sebuah IEnumerable<T>menjadi DataTableyang berisi kolom yang mewakili Tproperti, dengan satu baris untuk setiap item di 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;
}

Ini "agak" terlalu rumit, tetapi sebenarnya cukup bagus untuk melihat apa hasilnya, seperti yang bisa Anda berikan List<T>, misalnya:

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

Dan Anda akan mengembalikan DataTable dengan struktur:

Make (string)
YearOfManufacture (int)

Dengan satu baris per item di Anda List<Car>


1

Contoh ini memangkas semua properti string dari suatu objek.

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

Saya belum menemukan ini berfungsi, kata objek Aplikasi. Namun saya telah berhasil

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

string rval = serializer.Serialize(myAppObj);

2
Jangan gunakan JavaScriptSerializer jika Anda bisa menghindarinya. Ada banyak alasan .
Nuno André

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

Anda dapat mencoba ini:

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

Setelah setiap array mengimplementasikan antarmuka IEnumerable

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.