コード例 #1
0
 public void IfIsAssignableFrom <TType>([NoEnumeration] object instance, string message = null)
 {
     if (ReferenceEquals(instance, null) || PortableTypeInfo.IsAssignableFrom(instance, typeof(TType)))
     {
         throw string.IsNullOrEmpty(message) ? new TException() : NewWithMessage(message);
     }
 }
コード例 #2
0
        public void GetPublicPropertyValue_ShouldGetAllValuesForMyClass()
        {
            var x = new MyClass
            {
                A = 21,
                B = "PINO",
                C = decimal.One,
                D = Math.PI
            };

            var props = PortableTypeInfo.GetPublicProperties <MyClass>();

            Assert.AreEqual(x.A, PortableTypeInfo.GetPublicPropertyValue(x, props.First(p => p.Name == nameof(MyClass.A))));
            Assert.AreEqual(x.B, PortableTypeInfo.GetPublicPropertyValue(x, props.First(p => p.Name == nameof(MyClass.B))));
            Assert.AreEqual(x.C, PortableTypeInfo.GetPublicPropertyValue(x, props.First(p => p.Name == nameof(MyClass.C))));
            Assert.AreEqual(x.D, PortableTypeInfo.GetPublicPropertyValue(x, props.First(p => p.Name == nameof(MyClass.D))));

#if !(NETSTD10 || NETSTD11)
            var typeAccessor = Thrower.Reflection.FastMember.TypeAccessor.Create <MyClass>();
            Assert.AreEqual(x.A, PortableTypeInfo.GetPublicPropertyValue(typeAccessor, x, props.First(p => p.Name == nameof(MyClass.A))));
            Assert.AreEqual(x.B, PortableTypeInfo.GetPublicPropertyValue(typeAccessor, x, props.First(p => p.Name == nameof(MyClass.B))));
            Assert.AreEqual(x.C, PortableTypeInfo.GetPublicPropertyValue(typeAccessor, x, props.First(p => p.Name == nameof(MyClass.C))));
            Assert.AreEqual(x.D, PortableTypeInfo.GetPublicPropertyValue(typeAccessor, x, props.First(p => p.Name == nameof(MyClass.D))));
#endif
        }
コード例 #3
0
ファイル: TypeAccessor.cs プロジェクト: LSTANCZYK/Thrower
        private static bool IsFullyPublic(Type type, PropertyInfo[] props, bool allowNonPublicAccessors)
        {
            while (PortableTypeInfo.IsNestedPublic(type))
            {
                type = type.DeclaringType;
            }
            if (!PortableTypeInfo.IsPublic(type))
            {
                return(false);
            }

            if (allowNonPublicAccessors)
            {
                for (int i = 0; i < props.Length; i++)
                {
                    if (props[i].GetGetMethod(true) != null && props[i].GetGetMethod(false) == null)
                    {
                        return(false);                                                                             // non-public getter
                    }
                    if (props[i].GetSetMethod(true) != null && props[i].GetSetMethod(false) == null)
                    {
                        return(false);                                                                             // non-public setter
                    }
                }
            }

            return(true);
        }
コード例 #4
0
 /// <summary>
 ///   Throws an exception of type <typeparamref name="TException"/> if and only if specified
 ///   object has not given type.
 /// </summary>
 /// <param name="instance">The object to be tested.</param>
 /// <param name="type">The type the object must not have.</param>
 /// <param name="message">The optional message.</param>
 /// <exception cref="Exception">
 ///   If given condition is true, an exception of type <typeparamref name="TException"/> is thrown.
 /// </exception>
 public void IfIsNotInstanceOf([NoEnumeration] object instance, Type type, string message = null)
 {
     if (!PortableTypeInfo.IsInstanceOf(instance, type))
     {
         throw string.IsNullOrEmpty(message) ? new TException() : NewWithMessage(message);
     }
 }
コード例 #5
0
        /// <summary>
        ///   Formats given key-value pair in order to use it for <see cref="object.ToString"/>.
        /// </summary>
        /// <param name="pair">Key-value pair.</param>
        /// <returns>Formatted key-value pair.</returns>
        public static string ToString(KeyValuePair <string, object> pair)
        {
            var k = pair.Key;
            var v = pair.Value;

            if (v == null)
            {
                return($"{k}: null");
            }

            var s = v as string;

            if (s != null)
            {
                return($"{k}: \"{s}\"");
            }

            var t = v.GetType();

            if (PortableTypeInfo.IsPrimitive(t))
            {
                return($"{k}: {v}");
            }

            return($"{k}: {{{v}}}");
        }
コード例 #6
0
        public void GetPublicProperties_ShouldReturnAllPropertiesOfMyInterface()
        {
            var props = PortableTypeInfo.GetPublicProperties <MyInterface>();

            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyInterface.A)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyInterface.B)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyInterface.C)));
        }
コード例 #7
0
        public void GetPublicProperties_ShouldReturnAllPropertiesOfMyStruct()
        {
            var props = PortableTypeInfo.GetPublicProperties <MyStruct>();

            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyStruct.A)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyStruct.B)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyStruct.C)));
            Assert.AreEqual(0, props.Count(p => p.Name == "P"));
        }
コード例 #8
0
 /// <summary>
 ///   Ensures given enumeration value is defined in specified enumeration type.
 /// </summary>
 /// <typeparam name="TEnum">The enumeration type.</typeparam>
 /// <param name="value">The enumeration value.</param>
 /// <returns>
 ///   True if given enumeration value is defined in specified enumeration type, false otherwise.
 /// </returns>
 /// <remarks>This also works when enumeration has been decorated with <see cref="FlagsAttribute"/>.</remarks>
 public static bool Validate <TEnum>(TEnum?value)
     where TEnum : struct
 {
     if (!PortableTypeInfo.IsEnum(CachedEnumValidator <TEnum> .EnumType))
     {
         return(false);
     }
     return(value.HasValue ? Validate(value.Value) : true);
 }
コード例 #9
0
 private static ConstructorInfo GetCtor(IList <Type> ctorTypes)
 {
     return((from c in PortableTypeInfo.GetConstructors(typeof(TEx))
             let args = c.GetParameters()
                        let zipArgs = MyZip(args, ctorTypes, (argType, ctorType) => new { argType, ctorType })
                                      where args.Length == ctorTypes.Count &&
                                      (c.IsPublic || c.IsAssembly) &&
                                      zipArgs.All(t => ReferenceEquals(t.argType.ParameterType, t.ctorType))
                                      select c).FirstOrDefault());
 }
コード例 #10
0
        public void GetPublicProperties_ShouldReturnAllPropertiesOfMyClass()
        {
            var props = PortableTypeInfo.GetPublicProperties <MyClass>();

            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyClass.A)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyClass.B)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyClass.C)));
            Assert.AreEqual(1, props.Count(p => p.Name == nameof(MyAbstractClass.D)));
            Assert.AreEqual(0, props.Count(p => p.Name == "P"));
        }
コード例 #11
0
        /// <summary>
        ///   Ensures given enumeration value is defined in specified enumeration type.
        /// </summary>
        /// <param name="enumType">The enumeration type.</param>
        /// <param name="value">The enumeration value.</param>
        /// <returns>
        ///   True if given enumeration value is defined in specified enumeration type, false otherwise.
        /// </returns>
        /// <remarks>This also works when enumeration has been decorated with <see cref="FlagsAttribute"/>.</remarks>
        public static bool Validate(Type enumType, object value)
        {
            bool?isReallyAnEnum = null;

            if (PortableTypeInfo.IsGenericType(enumType) && ReferenceEquals(PortableTypeInfo.GetGenericTypeDefinition(enumType), typeof(Nullable <>)))
            {
                var innerEnumType = PortableTypeInfo.GetGenericTypeArguments(enumType)[0];
                isReallyAnEnum = PortableTypeInfo.IsEnum(innerEnumType);

                if (isReallyAnEnum.Value && ReferenceEquals(value, null))
                {
                    // Nullable enum with null value, OK.
                    return(true);
                }

                if (value.GetType() == enumType)
                {
                    if (!PortableTypeInfo.GetPublicPropertyValue <bool>(value, nameof(Nullable <byte> .HasValue)))
                    {
                        // OK if we are really handling an enumeration.
                        return(isReallyAnEnum.Value);
                    }
                    value = PortableTypeInfo.GetPublicPropertyValue(value, nameof(Nullable <byte> .Value));
                }

                // Overwrite enumeration type with the inner one, since we are sure that value has
                // that type; in fact, above if ensures that condition.
                enumType = innerEnumType;
            }

            if ((isReallyAnEnum.HasValue && !isReallyAnEnum.Value) || !PortableTypeInfo.IsEnum(enumType))
            {
                // If we are not handling an enum, then exit now.
                return(false);
            }
            if (Enum.IsDefined(enumType, value))
            {
                return(true);
            }

            var hasFlagsAttribute = TypeHasFlagsAttribute(enumType);

            if (hasFlagsAttribute)
            {
                var mask = 0;
                foreach (var enumValue in Enum.GetValues(enumType))
                {
                    mask = mask | (int)enumValue;
                }
                var intValue = (int)value;
                return((mask & intValue) == intValue);
            }

            return(false);
        }
コード例 #12
0
        /// <summary>
        ///   Ensures given enumeration value is defined in specified enumeration type.
        /// </summary>
        /// <typeparam name="TEnum">The enumeration type.</typeparam>
        /// <param name="value">The enumeration value.</param>
        /// <returns>
        ///   True if given enumeration value is defined in specified enumeration type, false otherwise.
        /// </returns>
        /// <remarks>This also works when enumeration has been decorated with <see cref="FlagsAttribute"/>.</remarks>
        public static bool Validate <TEnum>(TEnum value)
            where TEnum : struct
        {
            if (!PortableTypeInfo.IsEnum(CachedEnumValidator <TEnum> .EnumType))
            {
                return(false);
            }
            if (Enum.IsDefined(CachedEnumValidator <TEnum> .EnumType, value))
            {
                return(true);
            }
            if (CachedEnumValidator <TEnum> .HasFlagsAttribute)
            {
                var intValue = PortableTypeInfo.CastTo <int> .From(value);

                return((CachedEnumValidator <TEnum> .Mask & intValue) == intValue);
            }
            return(false);
        }
コード例 #13
0
ファイル: TypeAccessor.cs プロジェクト: LSTANCZYK/Thrower
 private static void Cast(ILGenerator il, Type type, bool valueAsPointer)
 {
     if (type == typeof(object))
     {
     }
     else if (PortableTypeInfo.IsValueType(type))
     {
         if (valueAsPointer)
         {
             il.Emit(OpCodes.Unbox, type);
         }
         else
         {
             il.Emit(OpCodes.Unbox_Any, type);
         }
     }
     else
     {
         il.Emit(OpCodes.Castclass, type);
     }
 }
コード例 #14
0
ファイル: StringExtensions.cs プロジェクト: LSTANCZYK/Thrower
        /// <summary>
        ///   Converts given string into the specified enumeration value, applying the specified
        ///   filter on casing.
        /// </summary>
        /// <typeparam name="TEnum">The type of the enumeration.</typeparam>
        /// <param name="enumString">The string value of one enumeration value.</param>
        /// <param name="ignoreCase">Whether to consider casing or not while parsing the string.</param>
        /// <returns>An enumeration value parsed from given string.</returns>
        /// <exception cref="InvalidOperationException">
        ///   Given type parameter <typeparamref name="TEnum"/> is not an enum.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   Given value cannot be mapped to any enum value.
        /// </exception>
        public static TEnum ToEnum <TEnum>(this string enumString, bool ignoreCase)
            where TEnum : struct
        {
            var enumType = typeof(TEnum);

            Raise.InvalidOperationException.IfNot(PortableTypeInfo.IsEnum(enumType), "Given type is not an enumeration");

#if NET35
            var enumValue = Enum.Parse(enumType, enumString, ignoreCase);
            if (Enum.IsDefined(enumType, enumValue))
            {
                return((TEnum)enumValue);
            }
#else
            TEnum enumValue;
            if (Enum.TryParse(enumString, ignoreCase, out enumValue))
            {
                return(enumValue);
            }
#endif

            throw new ArgumentException($"Given value is not available for {enumType.Name}", nameof(enumString));
        }
コード例 #15
0
ファイル: StringExtensions.cs プロジェクト: LSTANCZYK/Thrower
        /// <summary>
        ///   Converts given string into the specified enumeration value, applying the specified
        ///   filter on casing. If given string cannot be mapped to any enum value, then default
        ///   value for <typeparamref name="TEnum"/> is returned.
        /// </summary>
        /// <typeparam name="TEnum">The type of the enumeration.</typeparam>
        /// <param name="enumString">The string value of one enumeration value.</param>
        /// <param name="ignoreCase">Whether to consider casing or not while parsing the string.</param>
        /// <returns>
        ///   An enumeration value parsed from given string or default enum value if that is not possible.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        ///   Given type parameter <typeparamref name="TEnum"/> is not an enum.
        /// </exception>
        public static TEnum ToEnumOrDefault <TEnum>(this string enumString, bool ignoreCase)
            where TEnum : struct
        {
            var enumType = typeof(TEnum);

            Raise.InvalidOperationException.IfNot(PortableTypeInfo.IsEnum(enumType), "Given type is not an enumeration");

#if NET35
            var enumValue = Enum.Parse(enumType, enumString, ignoreCase);
            if (Enum.IsDefined(enumType, enumValue))
            {
                return((TEnum)enumValue);
            }
#else
            TEnum enumValue;
            if (Enum.TryParse(enumString, ignoreCase, out enumValue))
            {
                return(enumValue);
            }
#endif

            // Not found, return default value.
            return(default(TEnum));
        }
コード例 #16
0
 public void GetBaseType_ShouldReturnMyAbstractClass()
 {
     Assert.AreSame(typeof(MyAbstractClass), PortableTypeInfo.GetBaseType(typeof(MyClass)));
 }
コード例 #17
0
 public void IsValueType_ShouldReturnTrueWithStruct()
 {
     Assert.IsTrue(PortableTypeInfo.IsValueType(typeof(MyStruct)));
     Assert.IsTrue(PortableTypeInfo.IsValueType <MyStruct>());
 }
コード例 #18
0
 public void IsPrimitive_ShouldReturnFalseWithEnum()
 {
     Assert.IsFalse(PortableTypeInfo.IsPrimitive(typeof(MyEnum)));
     Assert.IsFalse(PortableTypeInfo.IsPrimitive <MyEnum>());
 }
コード例 #19
0
        private static bool ValidateInternal(object obj, string path, ValidateAttribute validation, IList <ValidationError> validationErrors)
        {
            if (ReferenceEquals(obj, null))
            {
                if (validation.Required)
                {
                    validationErrors.Add(new ValidationError(path, "Property is required, found null"));
                    return(false);
                }

                // If object is null, we cannot do anything else.
                return(true);
            }

            var objType = obj.GetType();

            if (AlwaysValidTypes.Contains(objType) || PortableTypeInfo.IsEnum(objType))
            {
                return(true);
            }

            var isValueType = PortableTypeInfo.IsValueType(objType);

            // Check whether this type is nullable.
            if (validation.Required && isValueType && PortableTypeInfo.IsGenericType(objType) && objType.GetGenericTypeDefinition() == typeof(Nullable <>))
            {
                var nullableProps        = PortableTypeInfo.GetPublicProperties(objType);
                var nullableHasValueProp = nullableProps.First(p => p.Name == nameof(Nullable <bool> .HasValue));

                if ((bool)PortableTypeInfo.GetPublicPropertyValue(obj, nullableHasValueProp))
                {
                    validationErrors.Add(new ValidationError(path, "Property is required, found null"));
                    return(false);
                }

                var nullableValueProp = nullableProps.First(p => p.Name == nameof(Nullable <bool> .Value));
                var nullableValue     = PortableTypeInfo.GetPublicPropertyValue(obj, nullableValueProp);
                return(ValidateInternal(nullableValue, path, validation, validationErrors));
            }

            var collection = obj as ICollection;

            if (collection != null)
            {
                var c = collection.Count;
                if (c < validation.CollectionItemsMinCount)
                {
                    validationErrors.Add(new ValidationError(path, $"Minimum item count is {validation.CollectionItemsMinCount}, found {c}"));
                }
                if (c > validation.CollectionItemsMaxCount)
                {
                    validationErrors.Add(new ValidationError(path, $"Maximum item count is {validation.CollectionItemsMaxCount}, found {c}"));
                }
            }

            var enumerable = obj as IEnumerable;

            if (enumerable != null && validation.Enumerable)
            {
                var itemValidation = new ValidateAttribute {
                    Required = validation.EnumerableItemsRequired
                };
                var index = 0;
                foreach (var item in enumerable)
                {
                    var indexedNewPath = $"{path}[{index++}]";
                    ValidateInternal(item, indexedNewPath, itemValidation, validationErrors);
                }
            }

            if (PortableTypeInfo.IsClass(objType) || isValueType)
            {
                var props    = PortableTypeInfo.GetPublicProperties(objType);
                var reqProps = from p in props
                               from a in PortableTypeInfo.GetCustomAttributes(p, false)
                               let v = a as ValidateAttribute
                                       where v != null
                                       select new { PropertyInfo = p, Validation = v };

#if !(NETSTD10 || NETSTD11) && FAST_MEMBER
                var typeAccessor = Reflection.FastMember.TypeAccessor.Create(objType);
#endif

                foreach (var rp in reqProps)
                {
                    var propertyInfo = rp.PropertyInfo;

#if !(NETSTD10 || NETSTD11) && FAST_MEMBER
                    var propertyValue = PortableTypeInfo.GetPublicPropertyValue(typeAccessor, obj, propertyInfo);
#else
                    var propertyValue = PortableTypeInfo.GetPublicPropertyValue(obj, propertyInfo);
#endif

                    var newPath = $"{path}.{propertyInfo.Name}";
                    ValidateInternal(propertyValue, newPath, rp.Validation, validationErrors);
                }

                return(validationErrors.Count == 0);
            }

            // Non dovrei mai finire qui!
            return(true);
        }
コード例 #20
0
 public void IsPrimitive_ShouldReturnFalseWithInterface()
 {
     Assert.IsFalse(PortableTypeInfo.IsPrimitive(typeof(MyInterface)));
 }
コード例 #21
0
 public void IsPrimitive_ShouldReturnFalseWithStruct()
 {
     Assert.IsFalse(PortableTypeInfo.IsPrimitive(typeof(MyStruct)));
     Assert.IsFalse(PortableTypeInfo.IsPrimitive <MyStruct>());
 }
コード例 #22
0
 public void IsPrimitive_ShouldReturnFalseWithAbstractClass()
 {
     Assert.IsFalse(PortableTypeInfo.IsPrimitive(typeof(MyAbstractClass)));
 }
コード例 #23
0
 private static bool TypeHasFlagsAttribute(Type enumType) => PortableTypeInfo
 .GetCustomAttributes(enumType, true)
 ?.Any(a => a is FlagsAttribute) ?? false;
コード例 #24
0
 public void IsPrimitive_ShouldReturnTrueWithPrimitive()
 {
     Assert.IsTrue(PortableTypeInfo.IsPrimitive(typeof(int)));
     Assert.IsTrue(PortableTypeInfo.IsPrimitive <int>());
 }
コード例 #25
0
ファイル: TypeAccessor.cs プロジェクト: LSTANCZYK/Thrower
        private static TypeAccessor CreateNew(Type type, bool allowNonPublicAccessors)
        {
#if !NET35
            if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(type))
            {
                return(DynamicAccessor.Singleton);
            }
#endif

            var props   = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var fields  = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
            var map     = new Dictionary <string, int>();
            var members = new List <MemberInfo>(props.Length + fields.Length);
            var i       = 0;
            foreach (var prop in props)
            {
                if (!map.ContainsKey(prop.Name) && prop.GetIndexParameters().Length == 0)
                {
                    map.Add(prop.Name, i++);
                    members.Add(prop);
                }
            }
            foreach (var field in fields)
            {
                if (!map.ContainsKey(field.Name))
                {
                    map.Add(field.Name, i++); members.Add(field);
                }
            }

            ConstructorInfo ctor = null;
            if (PortableTypeInfo.IsClass(type) && !PortableTypeInfo.IsAbstract(type))
            {
                ctor = type.GetConstructor(PortableTypeInfo.EmptyTypes);
            }
            ILGenerator il;
            if (!IsFullyPublic(type, props, allowNonPublicAccessors))
            {
                var dynGetter = new DynamicMethod(type.FullName + "_get", typeof(object), new Type[] { typeof(int), typeof(object) }, type, true);
                var dynSetter = new DynamicMethod(type.FullName + "_set", null, new Type[] { typeof(int), typeof(object), typeof(object) }, type, true);
                WriteMapImpl(dynGetter.GetILGenerator(), type, members, null, allowNonPublicAccessors, true);
                WriteMapImpl(dynSetter.GetILGenerator(), type, members, null, allowNonPublicAccessors, false);
                DynamicMethod dynCtor = null;
                if (ctor != null)
                {
                    dynCtor = new DynamicMethod(type.FullName + "_ctor", typeof(object), PortableTypeInfo.EmptyTypes, type, true);
                    il      = dynCtor.GetILGenerator();
                    il.Emit(OpCodes.Newobj, ctor);
                    il.Emit(OpCodes.Ret);
                }
                return(new DelegateAccessor(
                           map,
                           (Func <int, object, object>)dynGetter.CreateDelegate(typeof(Func <int, object, object>)),
                           (Action <int, object, object>)dynSetter.CreateDelegate(typeof(Action <int, object, object>)),
                           dynCtor == null ? null : (Func <object>)dynCtor.CreateDelegate(typeof(Func <object>)), type));
            }

            // note this region is synchronized; only one is being created at a time so we don't need
            // to stress about the builders
            if (assembly == null)
            {
                var name = new AssemblyName("FastMember_dynamic");
#if (NETSTD13 || NETSTD20)
                assembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
#else
                assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
#endif
                module = assembly.DefineDynamicModule(name.Name);
            }
#if (NETSTD13 || NETSTD20)
            var attribs = typeof(TypeAccessor).GetTypeInfo().Attributes;
#else
            var attribs = typeof(TypeAccessor).Attributes;
#endif
            var tb = module.DefineType("FastMember_dynamic." + type.Name + "_" + GetNextCounterValue(),
                                       (attribs | TypeAttributes.Sealed | TypeAttributes.Public) & ~(TypeAttributes.Abstract | TypeAttributes.NotPublic), typeof(RuntimeTypeAccessor));

            il = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] {
                typeof(Dictionary <string, int>)
            }).GetILGenerator();
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldarg_1);
            var mapField = tb.DefineField("_map", typeof(Dictionary <string, int>), FieldAttributes.InitOnly | FieldAttributes.Private);
            il.Emit(OpCodes.Stfld, mapField);
            il.Emit(OpCodes.Ret);

            var indexer    = typeof(TypeAccessor).GetProperty("Item");
            var baseGetter = indexer.GetGetMethod();
            var baseSetter = indexer.GetSetMethod();
            var body       = tb.DefineMethod(baseGetter.Name, baseGetter.Attributes & ~MethodAttributes.Abstract, typeof(object), new Type[] { typeof(object), typeof(string) });
            il = body.GetILGenerator();
            WriteMapImpl(il, type, members, mapField, allowNonPublicAccessors, true);
            tb.DefineMethodOverride(body, baseGetter);

            body = tb.DefineMethod(baseSetter.Name, baseSetter.Attributes & ~MethodAttributes.Abstract, null, new Type[] { typeof(object), typeof(string), typeof(object) });
            il   = body.GetILGenerator();
            WriteMapImpl(il, type, members, mapField, allowNonPublicAccessors, false);
            tb.DefineMethodOverride(body, baseSetter);

            MethodInfo baseMethod;
            if (ctor != null)
            {
                baseMethod = typeof(TypeAccessor).GetProperty(nameof(CreateNewSupported)).GetGetMethod();
                body       = tb.DefineMethod(baseMethod.Name, baseMethod.Attributes, baseMethod.ReturnType, PortableTypeInfo.EmptyTypes);
                il         = body.GetILGenerator();
                il.Emit(OpCodes.Ldc_I4_1);
                il.Emit(OpCodes.Ret);
                tb.DefineMethodOverride(body, baseMethod);

                baseMethod = typeof(TypeAccessor).GetMethod(nameof(CreateNew));
                body       = tb.DefineMethod(baseMethod.Name, baseMethod.Attributes, baseMethod.ReturnType, PortableTypeInfo.EmptyTypes);
                il         = body.GetILGenerator();
                il.Emit(OpCodes.Newobj, ctor);
                il.Emit(OpCodes.Ret);
                tb.DefineMethodOverride(body, baseMethod);
            }

            baseMethod = typeof(RuntimeTypeAccessor).GetProperty("Type", BindingFlags.NonPublic | BindingFlags.Instance).GetGetMethod(true);
            body       = tb.DefineMethod(baseMethod.Name, baseMethod.Attributes & ~MethodAttributes.Abstract, baseMethod.ReturnType, PortableTypeInfo.EmptyTypes);
            il         = body.GetILGenerator();
            il.Emit(OpCodes.Ldtoken, type);
            il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
            il.Emit(OpCodes.Ret);
            tb.DefineMethodOverride(body, baseMethod);

#if (NETSTD13 || NETSTD20)
            var typeToBeCreated = tb.CreateTypeInfo().AsType();
#else
            var typeToBeCreated = tb.CreateType();
#endif

            var accessor = (TypeAccessor)Activator.CreateInstance(typeToBeCreated, map);
            return(accessor);
        }
コード例 #26
0
ファイル: TypeAccessor.cs プロジェクト: LSTANCZYK/Thrower
        private static void WriteMapImpl(ILGenerator il, Type type, List <MemberInfo> members, FieldBuilder mapField, bool allowNonPublicAccessors, bool isGet)
        {
            OpCode obj, index, value;

            var fail = il.DefineLabel();

            if (mapField == null)
            {
                index = OpCodes.Ldarg_0;
                obj   = OpCodes.Ldarg_1;
                value = OpCodes.Ldarg_2;
            }
            else
            {
                il.DeclareLocal(typeof(int));
                index = OpCodes.Ldloc_0;
                obj   = OpCodes.Ldarg_1;
                value = OpCodes.Ldarg_3;

                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, mapField);
                il.Emit(OpCodes.Ldarg_2);
                il.Emit(OpCodes.Ldloca_S, (byte)0);
                il.EmitCall(OpCodes.Callvirt, tryGetValue, null);
                il.Emit(OpCodes.Brfalse, fail);
            }
            var labels = new Label[members.Count];

            for (int i = 0; i < labels.Length; i++)
            {
                labels[i] = il.DefineLabel();
            }
            il.Emit(index);
            il.Emit(OpCodes.Switch, labels);
            il.MarkLabel(fail);
            il.Emit(OpCodes.Ldstr, "name");
            il.Emit(OpCodes.Newobj, typeof(ArgumentOutOfRangeException).GetConstructor(new Type[] { typeof(string) }));
            il.Emit(OpCodes.Throw);
            for (int i = 0; i < labels.Length; i++)
            {
                il.MarkLabel(labels[i]);
                var          member = members[i];
                var          isFail = true;
                FieldInfo    field;
                PropertyInfo prop;
                if ((field = member as FieldInfo) != null)
                {
                    il.Emit(obj);
                    Cast(il, type, true);
                    if (isGet)
                    {
                        il.Emit(OpCodes.Ldfld, field);
                        if (PortableTypeInfo.IsValueType(field.FieldType))
                        {
                            il.Emit(OpCodes.Box, field.FieldType);
                        }
                    }
                    else
                    {
                        il.Emit(value);
                        Cast(il, field.FieldType, false);
                        il.Emit(OpCodes.Stfld, field);
                    }
                    il.Emit(OpCodes.Ret);
                    isFail = false;
                }
                else if ((prop = member as PropertyInfo) != null)
                {
                    MethodInfo accessor;
                    if (prop.CanRead && (accessor = isGet ? prop.GetGetMethod(allowNonPublicAccessors) : prop.GetSetMethod(allowNonPublicAccessors)) != null)
                    {
                        il.Emit(obj);
                        Cast(il, type, true);
                        if (isGet)
                        {
                            il.EmitCall(PortableTypeInfo.IsValueType(type) ? OpCodes.Call : OpCodes.Callvirt, accessor, null);
                            if (PortableTypeInfo.IsValueType(prop.PropertyType))
                            {
                                il.Emit(OpCodes.Box, prop.PropertyType);
                            }
                        }
                        else
                        {
                            il.Emit(value);
                            Cast(il, prop.PropertyType, false);
                            il.EmitCall(PortableTypeInfo.IsValueType(type) ? OpCodes.Call : OpCodes.Callvirt, accessor, null);
                        }
                        il.Emit(OpCodes.Ret);
                        isFail = false;
                    }
                }
                if (isFail)
                {
                    il.Emit(OpCodes.Br, fail);
                }
            }
        }
コード例 #27
0
 /// <summary>
 ///   Gets attribute type.
 /// </summary>
 /// <param name="attributeType">The attribute type.</param>
 /// <param name="inherit">
 ///   If true, specifies to also search the ancestors of element for custom attributes.
 /// </param>
 public Attribute GetAttribute(Type attributeType, bool inherit) => PortableTypeInfo
 .GetCustomAttributes(member, inherit)
 .FirstOrDefault(a => PortableTypeInfo.IsInstanceOf(a, attributeType));
コード例 #28
0
ファイル: ObjectReader.cs プロジェクト: LSTANCZYK/Thrower
#pragma warning restore CC0022 // Should dispose object

        /// <summary>
        ///   Creates a new ObjectReader instance for reading the supplied data.
        /// </summary>
        /// <param name="type">The expected Type of the information to be read.</param>
        /// <param name="source">The sequence of objects to represent.</param>
        /// <param name="members">The members that should be exposed to the reader.</param>
        public ObjectReader(Type type, IEnumerable source, params string[] members)
        {
            if (source == null)
            {
                throw new ArgumentOutOfRangeException(nameof(source));
            }

            var allMembers = members == null || members.Length == 0;

            this._accessor = TypeAccessor.Create(type);
            if (_accessor.GetMembersSupported)
            {
                var typeMembers = this._accessor.GetMembers();

                if (allMembers)
                {
                    members = new string[typeMembers.Count];
                    for (int i = 0; i < members.Length; i++)
                    {
                        members[i] = typeMembers[i].Name;
                    }
                }

                this._allowNull      = new BitArray(members.Length);
                this._effectiveTypes = new Type[members.Length];
                for (int i = 0; i < members.Length; i++)
                {
                    Type memberType = null;
                    var  allowNull  = true;
                    var  hunt       = members[i];
                    foreach (var member in typeMembers)
                    {
                        if (member.Name == hunt)
                        {
                            if (memberType == null)
                            {
                                var tmp = member.Type;
                                memberType = Nullable.GetUnderlyingType(tmp) ?? tmp;

                                allowNull = !(PortableTypeInfo.IsValueType(memberType) && memberType == tmp);

                                // but keep checking, in case of duplicates
                            }
                            else
                            {
                                memberType = null; // duplicate found; say nothing
                                break;
                            }
                        }
                    }
                    this._allowNull[i]      = allowNull;
                    this._effectiveTypes[i] = memberType ?? typeof(object);
                }
            }
            else if (allMembers)
            {
                throw new InvalidOperationException("Member information is not available for this type; the required members must be specified explicitly");
            }

            this._current     = null;
            this._memberNames = (string[])members.Clone();

            this._source = source.GetEnumerator();
        }
コード例 #29
0
 public void IsValueType_ShouldReturnFalseWithClass()
 {
     Assert.IsFalse(PortableTypeInfo.IsValueType(typeof(MyClass)));
 }
コード例 #30
0
 public void IsValueType_ShouldReturnTrueWithEnum()
 {
     Assert.IsTrue(PortableTypeInfo.IsValueType(typeof(MyEnum)));
     Assert.IsTrue(PortableTypeInfo.IsValueType <MyEnum>());
 }