2

アプリケーションには、Nullable <int>のFieldInfoを持つコードがあり、次のサンプルのようにnull許容値(基になる値ではない)を取得する必要があります。

class Test
{
    public int? value;
}

public class Program
{
    static void Main(string[] args)
    {
        var obj = new Test { value = 10 };
        var fld = typeof (Test).GetField("value");
        var v = fld.GetValue(obj);

        System.Diagnostics.Debug.WriteLine(v.GetType().FullName);
        System.Diagnostics.Debug.WriteLine(fld.FieldType.FullName);
     }
 }

私の問題は、vには常にnullable(このサンプルではNullable <int>)ではなく基になる値(このサンプルではint )が割り当てられることです。

PS:実際のアプリケーションには、コンパイル時にnull許容型がないため、キャストはできません。

助けてくれてありがとう。

4

2 に答える 2

4

この場合vはタイプobjectです。valueがnullの場合、nullvになります。valueが整数の場合v、その整数になります。あなたvが実際にタイプを持ちたいならNullable<int>、あなたはそれをそのように宣言しなければなりません:var v = (int?) fld.GetValue(obj);

ボックス化された値を参照して取得できるようにする必要がある場合は、 null許容であっv.Valueたという事実を記録する必要があります( )。コンパイル時がわからないため、ジェネリックはここでは役に立ちません。fldNullable.GetUnderlyingType(fld.FieldType) != nullT

使用できるヘルパーは次のとおりです。

struct NullableObject
{
    public object Value { get; private set; }

    public static object GetField(object Target, FieldInfo Field)
    {
        object value = Field.GetValue(Target);
        if (Nullable.GetUnderlyingType(Field.FieldType) != null)
            return new NullableObject { Value = value };
        return value;
    }
}

public static class NullableHelper
{
    public static object GetNullableValue(this FieldInfo field, object target)
    {
        return NullableObject.GetField(target, field);
    }
}

次に、を呼び出す代わりにvar v = fld.GetValue(obj);、と言いvar v = fld.GetNullableValue(obj);ます。fldNullable型を表す場合は、Valueプロパティを持つオブジェクトを取得します。そうでない場合は、値を取得するだけです。

于 2011-11-22T01:36:33.730 に答える
0

まず、PropertyInfo オブジェクトの配列で「Test」クラスのすべてのプロパティを取得する必要があります。ループを形成し、各 PropertyInfo の「PropertyType」プロパティの「GetGenericTypeDefinition」メソッドを呼び出し、Nullable 型と比較します。ジェネリック型かどうかも確認してください。両方が true の場合、その PropertyInfo の「PropertyType」プロパティの「GetGenericArguments」メソッドを呼び出します。これは、「Type」オブジェクトの配列を返します。その最初の要素を取ります。これが必要なタイプになります。

複数の null 許容型がある場合は、「PropertyInfo.Name」でプロパティの名前を取得し、それに応じて比較できます。

以下は、あなたの都合に合わせて試して変更できるコードです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Nullable_Demo
{
    class Test
    {
        public int? value { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var obj = new Test { value = 10 };
            //var fld = typeof(Test).GetField("value");
            //var v = fld.GetValue(obj);

            Type typeobjs = obj.GetType();
            PropertyInfo[] piObjs = typeobjs.GetProperties();

            foreach (PropertyInfo piObj in piObjs)
            {
                Type typeDefinedInNullable;

                // Test for Nullable
                bool isNullable = piObj.PropertyType.IsGenericType &&
                    piObj.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);

                if (isNullable)
                {
                    // Returns the basic data type without reference to Nullable (for example, System.Int32)
                    typeDefinedInNullable = piObj.PropertyType.GetGenericArguments()[0];
                }
            }
        }
    }

}
于 2011-11-23T05:28:52.680 に答える