5

リフレクションに取り組んでいますが、再帰を実行しているときにスタックします。

コード:

public class User {
  public string Name;
  public int Number;
  public Address Address;    
}


public class Address {
 public string Street;
 public string State;
 public string Country;
}

今、私は値を印刷しています。

 Type t = user.GetType();  
 PropertyInfo[] props = t.GetProperties(); 
 foreach (PropertyInfo prp in props)  
 {  
   if(!prp.GetType().IsPrimitive && prp.GetType().IsClass) 
   {
     // Get the values of the Inner Class.
     // i am stucked over here , can anyone help me with this.

           Type ty = prp.GetType();
           var prpI = ty.GetProperties();
           //var tp = ty.GetType().;
            foreach (var propertyInfo in prpI)
            {
            var value = propertyInfo.GetValue(prp);
            var stringValue = (value != null) ? value.ToString() : "";
            console.WriteLine(prp.GetType().Name + "." + propertyInfo.Name+" Value : " +stringValue);    
            }
   }
   else
   {    
     var value = prp.GetValue(user);   
     var stringValue = (value != null) ? value.ToString() : "";
     console.writeline(user.GetType().Name + "." + prp.Name+" Value : " +stringValue); 
   }
 }

プロパティがクラスであるかプリミティブであるかを確認する方法を知りたいです。クラスの場合は再帰を実行します。

4

5 に答える 5

3

まず、本当に必要な場合を除いて、リフレクションの使用は避けてください。それは遅いです、それは散らかっています、それはデバッグ不可能な境界線です(そして私はそれが大好きです、しかしそれは別のことです)

オブジェクトのコンテンツ全体をダンプしたい場合は、それをオブジェクト自体に転送することをお勧めします。オブジェクトは内部の状態を知っている必要があります。オブジェクトToStringメソッドを使用して内部状態を記述したり、内部状態を表示するためのインターフェイスを定義したりできます。

interface IStateDisplay
{
   string GetInnerState();
}

オブジェクトにそれを実装させます。次に、プロパティを表示するためのコードは次のようになります

Console.WriteLine(user.GetInnerState());

もう1つのオプションは、AutoMapperのようなツールを使用することです。このツールは、反射の複雑さと複雑さを隠し、使用するための優れたAPIを公開します。

ただし、リフレクションについて学習している場合は、複雑なオブジェクトの状態を印刷することは良い練習になります。その方向へのいくつかの指針:

public string Name;

はプロパティではなく、フィールドであるため、type.GetProperties()返されません。C#プロパティとは何か、およびそれらがどのように使用および定義されているかを確認してください。最小限のプロパティ宣言は

public string Name {get; set;}

また、含まれているプロパティのタイプではなく、タイプprp.GetType()のタイプ情報を返します。PropertyInfoこの場合に必要なのはprp.PropertyTypeプロパティです。

Type.IsPrimitive次に、チェックはあなたが望むものではないと思います。このプロパティは、Boolean、Byte、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、IntPtr、UIntPtr、Char、Double、およびSingleタイプの場合はtrueを返し、それ以外の場合はfalseを返します。最も重要なのtypeof(string).IsPrimitiveはfalseを返します。

Type.IsClass同じように、チェックもあなたが望むものではないと思います。これを使用している場合、プロパティが値または参照型であるかどうかのみをチェックします。値タイプ(struct)も非常に複雑で、独自のプロパティとフィールドを含む可能性があるため、チェックは意味がありません。

于 2013-02-04T10:04:55.747 に答える
0

ありがとう@Sloth、あなたのコードはとても便利です。これは、「オブジェクト参照がオブジェクトのインスタンスに設定されていません。」エラー。null のオブジェクトのインスタンスを作成し、配列も処理します。考えられるすべてのコレクション タイプを処理するには、さらに多くのことを行う必要がありますが、これが始まりです。

public static IEnumerable<string> GetPropertInfos(object o, string parent = null)
    {


        Type t = o.GetType();
        //   String namespaceValue = t.Namespace;


        PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (PropertyInfo prp in props)
        {
            if (prp.PropertyType.Module.ScopeName != "CommonLanguageRuntimeLibrary")
            {
                // fix me: you have to pass parent + "." + t.Name instead of t.Name if parent != null
                object value = prp.GetValue(o);
                if (value == null)
                {

                    value =
                        Activator.CreateInstance(Type.GetType(
                            (prp.PropertyType).AssemblyQualifiedName.Replace("[]", "")));
                }

                var propertInfos = GetPropertInfos(value, t.Name);
                foreach (var info in propertInfos)
                    yield return info;
            }
            else
            {
                var type = GetTypeName(prp);

                var info = t.Name + "." + prp.Name ;
                if (String.IsNullOrWhiteSpace(parent))
                    yield return info;
                else
                    yield return parent + "." + info;
            }
        }
    }
于 2015-10-26T13:37:37.570 に答える
0
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;


namespace Extensions
{
    public static class ObjectExtension
    {
        public static string ToStringProperties(this object o)
        {
            return o.ToStringProperties(0);
        }
    public static string ToStringProperties(this object o, int level)
    {
        StringBuilder sb = new StringBuilder();
        string spacer = new String(' ', 2 * level);
        if (level == 0) sb.Append(o.ToString());
        sb.Append(spacer);
        sb.Append("{\r\n");
        foreach (PropertyInfo pi in o.GetType().GetProperties())
        {
        if (pi.GetIndexParameters().Length == 0)
        {
            sb.Append(spacer);
            sb.Append("  ");
            sb.Append(pi.Name);
            sb.Append(" = ");

            object propValue = pi.GetValue(o, null);
            if (propValue == null)
            {
                sb.Append(" <null>");
            } else {
                if (IsMyOwnType(pi.PropertyType))
                {
                    sb.Append("\r\n");
                    sb.Append(((object)propValue).ToStringProperties(level + 1));
                } else{
                    sb.Append(propValue.ToString());
                }
            }
            sb.Append("\r\n");
        }
    }
    sb.Append(spacer);
    sb.Append("}\r\n");
    return sb.ToString();
}
    private static bool IsMyOwnType(Type t) 
{
    return (t.Assembly == Assembly.GetExecutingAssembly());
}
}
}
于 2013-02-04T09:39:13.533 に答える
-1

物件をご利用Type.IsValueTypeいただけます。

于 2013-02-04T09:47:17.310 に答える