web-dev-qa-db-ja.com

不明なオブジェクトからプロパティと値を取得する

PHPの世界から、C#を試してみることにしました。私は検索したことがありますが、これに相当する方法の答えを見つけることができないようです。

$object = new Object();

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

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

基本的にオブジェクトのリストがあります。オブジェクトは3つの異なるタイプのいずれかであり、パブリックプロパティのセットを持ちます。オブジェクトのプロパティのリストを取得し、それらをループしてからファイルに書き出すことができるようにしたいのです。これはc#のリフレクションと関係があると思いますが、それはすべて私にとって新しいことです。

どんな助けも大歓迎です。

134
m4rc

これはそれを行う必要があります:

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
}
248
Cocowalla

はい、反射が進むべき道です。最初に、リスト内のインスタンスのタイプ(実行時)を表す TypeNAME_ を取得します。これを行うには、GetTypename__で Objectname__メソッドを呼び出します 。これはObjectname__クラスにあるため、.NETの every オブジェクトから呼び出し可能です。すべてのタイプがObjectname__から派生しているためです( まあ、技術的には、すべてではない 、しかしそれは重要ではありませんここに)。

Typename__インスタンスを取得したら、 GetPropertiesname__メソッドを呼び出してPropertyInfoname__のプロパティに関するランタイム情報を表す TypeNAME_ インスタンスを取得できます。

注:GetPropertiesname__のオーバーロードを使用して、取得する which プロパティの分類に役立てることができます。

そこから、情報をファイルに書き出すだけです。

上記のコードを翻訳すると、次のようになります。

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

メソッド情報またはフィールド情報が必要な場合は、 GetMethodsNAME_ または GetFieldsNAME_ メソッドのオーバーロードのいずれかをそれぞれ呼び出す必要があることに注意してください。

また、ファイルのメンバーをリストすることも1つですが、プロパティセットに基づいてロジックを駆動するためにこの情報を使用するべきではありません /

型の実装を制御できると仮定すると、共通の基本クラスから派生するか、共通のインターフェイスを実装してそれらを呼び出す必要があります( asNAME_ または isNAME_ 演算子を使用して、実行時に使用している基本クラス/インターフェース)。

ただし、これらの型定義を制御せず、パターンマッチングに基づいてロジックを駆動する必要がある場合は、問題ありません。

17
casperOne
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);
}
15
Vo Van Khoa

まあ、C#でも同様です。最も単純な例の1つを次に示します(パブリックプロパティのみ):

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

プロパティ名から特定のプロパティ値を取得するには

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

GetType-GetProperties-Linq Foreach:を使用できます。

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

以下は、IEnumerable<T>DataTableの各項目ごとに1つの行を持つ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行

2
Rob

この例では、オブジェクトのすべての文字列プロパティをトリミングします。

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);
    }
}
1
Brian Paske

これが機能することを発見していません、例えばアプリケーションオブジェクト。しかし、私は成功しました

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

string rval = serializer.Serialize(myAppObj);
0
jcsubmit