if a type is anonymous based on the language spec. - CSharp System.Reflection

CSharp examples for System.Reflection:Type

Description

if a type is anonymous based on the language spec.

Demo Code


using System.Threading.Tasks;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.CompilerServices;
using System.Reflection.Emit;
using System.Reflection;
using System.Linq;
using System.IO;//  w w  w . j av  a 2s .  c  o  m
using System.Globalization;
using System.Collections.Generic;
using System;

public class Main{
        /// <summary>
        /// HACK: This is a best effort attempt to divine if a type is anonymous based on the language spec.
        /// 
        /// Reference section 7.6.10.6 of the C# language spec as of 2012/11/19
        /// 
        /// It checks:
        ///     - is a class
        ///     - descends directly from object
        ///     - has [CompilerGenerated]
        ///     - has a single constructor
        ///     - that constructor takes exactly the same parameters as its public properties
        ///     - all public properties are not writable
        ///     - has a private field for every public property
        ///     - overrides Equals(object)
        ///     - overrides GetHashCode()
        /// </summary>
        public static bool IsAnonymouseClass(this Type type) // don't fix the typo, it's fitting.
        {
            if (type.IsValueType()) return false;
            if (type.BaseType() != typeof(object)) return false;

            var compilerGenerated = type.GetTypeInfo().CustomAttributes.Any(a => a.AttributeType == typeof(CompilerGeneratedAttribute));
            if (!compilerGenerated) return false;

            var allCons = type.GetConstructors();
            if (allCons.Length != 1) return false;

            var cons = allCons[0];
            if (!cons.IsPublic) return false;

            var props = type.GetProperties();
            if (props.Any(p => p.CanWrite)) return false;

            var propTypes = props.Select(t => t.PropertyType).ToList();

            foreach (var param in cons.GetParameters())
            {
                if (!propTypes.Contains(param.ParameterType)) return false;

                propTypes.Remove(param.ParameterType);
            }

            if (propTypes.Count != 0) return false;

            var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
            if (fields.Any(f => !f.IsPrivate)) return false;

            propTypes = props.Select(t => t.PropertyType).ToList();
            foreach (var field in fields)
            {
                if (!propTypes.Contains(field.FieldType)) return false;

                propTypes.Remove(field.FieldType);
            }

            if (propTypes.Count != 0) return false;

            var equals = type.GetMethod("Equals", new Type[] { typeof(object) });
            var hashCode = type.GetMethod("GetHashCode", new Type[0]);

            if (!equals.IsOverride() || !hashCode.IsOverride()) return false;

            return true;
        }
        public static bool IsOverride(this MethodInfo method)
        {
            return method.GetBaseDefinition() != method;
        }
        public static bool IsPublic(this Type type)
        {
            var info = type.GetTypeInfo();

            return info.IsPublic;
        }
        public static bool IsValueType(this Type type)
        {
            var info = type.GetTypeInfo();

            return info.IsValueType;
        }
        public static Type BaseType(this Type type)
        {
            var info = type.GetTypeInfo();

            return info.BaseType;
        }
        public static MethodInfo GetMethod(this Type type, string name, BindingFlags flags, Type[] parameterTypes)
        {
            var info = type.GetTypeInfo();
            var mtds = info.GetMethods(flags).Where(m => m.Name == name);

            foreach (var mtd in mtds)
            {
                var ps = mtd.GetParameters();
                if (ps.Length != parameterTypes.Length) continue;

                var allMatch = true;
                for (var i = 0; i < ps.Length; i++)
                {
                    var p = ps[i].ParameterType;
                    var pt = parameterTypes[i];
                    if (p != pt)
                    {
                        allMatch = false;
                    }
                }

                if (allMatch)
                {
                    return mtd;
                }
            }

            return null;
        }
}

Related Tutorials