チェンジセット 1507 (default)


以下の違いを無視:
日時:
2021/05/27 18:30:19 (3年前)
更新者:
hizuya@…
ログメッセージ:
  • ディクショナリ型のキーと値の型を取得するメソッドを追加。
場所:
framework/trunk
ファイル:
2個の更新

凡例:

未変更
追加
削除
  • framework/trunk/CoreLibrary/Sources/Reflection/ReflectionUtility.cs

    r1328 r1507  
    2424{ 
    2525    using System; 
     26    using System.Collections; 
    2627    using System.Collections.Generic; 
    2728    using System.Diagnostics.CodeAnalysis; 
     
    292293 
    293294        /// <summary> 
     295        /// 辞書のキーと値の型を取得します。 
     296        /// </summary> 
     297        /// <param name="type">辞書の型。</param> 
     298        /// <param name="keyType">辞書のキーの型。</param> 
     299        /// <param name="valueType">辞書の値の型。</param> 
     300        /// <returns> 
     301        /// <paramref name="type"/> が辞書の場合は <see langword="true"/>。 
     302        /// それ以外の場合は <see langword="false"/>。 
     303        /// </returns> 
     304        public static bool DetectDictionaryMemberType(Type type, out Type keyType, out Type valueType) 
     305        { 
     306            if (type == null) 
     307            { 
     308                keyType = null; 
     309                valueType = null; 
     310                return false; 
     311            } 
     312 
     313            // IDictionary<,> の実装を探す 
     314            for (Type targetType = type; targetType != typeof(object); targetType = targetType.BaseType) 
     315            { 
     316                if (!targetType.IsGenericType || targetType.IsGenericTypeDefinition) 
     317                { 
     318                    continue; 
     319                } 
     320 
     321                Type[] genericArguments = targetType.GetGenericArguments(); 
     322                if (genericArguments.Length != 2) 
     323                { 
     324                    continue; 
     325                } 
     326 
     327                Type genericDictionaryInterfaceType = typeof(IDictionary<,>).MakeGenericType(genericArguments); 
     328                if (genericDictionaryInterfaceType.IsAssignableFrom(targetType)) 
     329                { 
     330                    keyType = genericArguments[0]; 
     331                    valueType = genericArguments[1]; 
     332                    return true; 
     333                } 
     334            } 
     335 
     336            // IDictionary を実装している場合 
     337            if (typeof(IDictionary).IsAssignableFrom(type)) 
     338            { 
     339                keyType = typeof(object); 
     340                valueType = typeof(object); 
     341                return true; 
     342            } 
     343 
     344            keyType = null; 
     345            valueType = null; 
     346            return false; 
     347        } 
     348 
     349        /// <summary> 
    294350        /// キャスト演算子を使用して値をキャストします。 
    295351        /// </summary> 
  • framework/trunk/CoreTest/Sources/Reflection/ReflectionUtilityTest.cs

    r1328 r1507  
    2222namespace FCSoft.SilverFrost.Framework.Reflection 
    2323{ 
     24    using System; 
     25    using System.Collections; 
     26    using System.Collections.Generic; 
     27    using System.Collections.Specialized; 
    2428    using System.Diagnostics; 
    2529    using System.Reflection; 
     30    using FCSoft.SilverFrost.Framework.Collection; 
    2631    using NUnit.Framework; 
    2732 
     
    146151        } 
    147152 
     153        /// <summary> 
     154        /// <see cref="ReflectionUtility.DetectDictionaryMemberType"/> をテストします。 
     155        /// </summary> 
     156        /// <param name="type">辞書の型。</param> 
     157        /// <param name="expectedKeyType">検出されるべきキーの型。</param> 
     158        /// <param name="expectedValueType">検出されるべき値の型。</param> 
     159        /// <returns> 
     160        /// <paramref name="type"/> が辞書の場合は <see langword="true"/>。 
     161        /// それ以外の場合は <see langword="false"/>。 
     162        /// </returns> 
     163        [Test] 
     164        [TestCase(typeof(IDictionary<int, string>), typeof(int), typeof(string), ExpectedResult = true)] 
     165        [TestCase(typeof(Dictionary<int, string>), typeof(int), typeof(string), ExpectedResult = true)] 
     166        [TestCase(typeof(ExtendedDictionary), typeof(int), typeof(string), ExpectedResult = true)] 
     167        [TestCase(typeof(HalfExtendedDictionary<string>), typeof(int), typeof(string), ExpectedResult = true)] 
     168        [TestCase(typeof(FullExtendedDictionary), typeof(int), typeof(string), ExpectedResult = true)] 
     169        [TestCase(typeof(OrderedDictionary<int, string>), typeof(int), typeof(string), ExpectedResult = true)] 
     170        [TestCase(typeof(Hashtable), typeof(object), typeof(object), ExpectedResult = true)] 
     171        [TestCase(typeof(OrderedDictionary), typeof(object), typeof(object), ExpectedResult = true)] 
     172        [TestCase(typeof(object), null, null, ExpectedResult = false)] 
     173        [TestCase(typeof(string), null, null, ExpectedResult = false)] 
     174        [TestCase(null, null, null, ExpectedResult = false)] 
     175        public bool TestDetectDictionaryMemberType(Type type, Type expectedKeyType, Type expectedValueType) 
     176        { 
     177            Type keyType; 
     178            Type valueType; 
     179            bool result = ReflectionUtility.DetectDictionaryMemberType(type, out keyType, out valueType); 
     180            Assert.That(keyType, Is.EqualTo(expectedKeyType), "keyType"); 
     181            Assert.That(valueType, Is.EqualTo(expectedValueType), "valueType"); 
     182 
     183            return result; 
     184        } 
     185 
    148186 
    149187        // ReSharper disable UnusedMember.Local 
     
    165203 
    166204 
     205 
     206        /// <summary> 
     207        /// ディクショナリの実装型です。 
     208        /// </summary> 
     209        public class ExtendedDictionary : 
     210            Dictionary<int, string> 
     211        { 
     212            /// <summary> 
     213            /// インスタンスを作成します。 
     214            /// </summary> 
     215            internal ExtendedDictionary() 
     216            { 
     217                // AVOID 
     218            } 
     219        } 
     220 
     221        /// <summary> 
     222        /// キーのみを固定したディクショナリの実装型です。 
     223        /// </summary> 
     224        /// <typeparam name="T">値の型。</typeparam> 
     225        public class HalfExtendedDictionary<T> : 
     226            Dictionary<int, T> 
     227        { 
     228            /// <summary> 
     229            /// インスタンスを作成します。 
     230            /// </summary> 
     231            internal HalfExtendedDictionary() 
     232            { 
     233                // AVOID 
     234            } 
     235        } 
     236 
     237        /// <summary> 
     238        /// 値を固定したディクショナリの実装型です。 
     239        /// </summary> 
     240        public class FullExtendedDictionary : 
     241            HalfExtendedDictionary<string> 
     242        { 
     243            /// <summary> 
     244            /// インスタンスを作成します。 
     245            /// </summary> 
     246            internal FullExtendedDictionary() 
     247            { 
     248                // AVOID 
     249            } 
     250        } 
     251 
    167252        /// <summary> 
    168253        /// 他の型からキャストされる型です。 
詳しい使い方は TracChangeset を参照してください。