how to get all primitive type of an object

前端 未结 4 1624
夕颜
夕颜 2020-12-20 01:23

I wanna have all properties of an object which have primitive type, and if the object has a relation to another class , I wanna have the primitive properties of this another

相关标签:
4条回答
  • 2020-12-20 01:48

    I am bored at work waiting for a build, have fun with your homework ;)

    namespace Scratchpad
    {
        public static class TypeExtractor
        {
            public static IEnumerable<Type> ExtractTypes(this Type owner, HashSet<Type> visited = null)
            {
                if (visited == null)
                    visited = new HashSet<Type>();
    
                if (visited.Contains(owner))
                    return new Type[0];
    
                visited.Add(owner);
    
                switch (Type.GetTypeCode(owner))
                {
                    case TypeCode.Object:
                        break;
                    case TypeCode.Empty:
                        return new Type[0];
                    default:
                        return new[] {owner};
                }
    
                return
                    owner.GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance |
                                     BindingFlags.Static |
                                     BindingFlags.FlattenHierarchy)
                        .SelectMany(x => x.ExtractTypes(visited)).Union(new[] {owner}).Distinct();
            }
    
            public static IEnumerable<Type> ExtractTypes(this MemberInfo member, HashSet<Type> visited)
            {
                switch (member.MemberType)
                {
                    case MemberTypes.Property:
                        return ((PropertyInfo) member).PropertyType.ExtractTypes(visited);
                        break;
                    case MemberTypes.Field:
                        return ((FieldInfo) member).FieldType.ExtractTypes(visited);
                    default:
                        return new Type[0];
                }
            }
        }
    
        public class A
        {
            public string Name { get; set; }
            public B B { get; set; }
        }
    
    
        public class B
        {
            public string Category { get; set; }
            public A A { get; set; }
        }
    
        internal class Program
        {
            private static void Main(string[] args)
            {
                var q = typeof (A).ExtractTypes();
                foreach (var type in q)
                {
                    Console.Out.WriteLine(type.Name);
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-20 02:01

    You could keep a track of visited types to avoid recursion:

    public class A
    {
        public string Name { get; set; }
        public B B { get; set; }
    }
    
    public class B
    {
        public string Category { get; set; }
        public A A { get; set; }
    }
    
    class Program
    {
        static void Main()
        {
            var result = Visit(typeof(A));
            foreach (var item in result)
            {
                Console.WriteLine(item.Name);
            }
        }
    
        public static IEnumerable<PropertyInfo> Visit(Type t)
        {
            var visitedTypes = new HashSet<Type>();
            var result = new List<PropertyInfo>();
            InternalVisit(t, visitedTypes, result);
            return result;
        }
    
        private void InternalVisit(Type t, HashSet<Type> visitedTypes, IList<PropertyInfo> result)
        {
            if (visitedTypes.Contains(t))
            {
                return;
            }
    
            if (!IsPrimitive(t))
            {
                visitedTypes.Add(t);
                foreach (var property in t.GetProperties())
                {
                    if (IsPrimitive(property.PropertyType))
                    {
                        result.Add(property);
                    }
                    InternalVisit(property.PropertyType, visitedTypes, result);
                }
            }
        }
    
        private static bool IsPrimitive(Type t)
        {
            // TODO: put any type here that you consider as primitive as I didn't
            // quite understand what your definition of primitive type is
            return new[] { 
                typeof(string), 
                typeof(char),
                typeof(byte),
                typeof(sbyte),
                typeof(ushort),
                typeof(short),
                typeof(uint),
                typeof(int),
                typeof(ulong),
                typeof(long),
                typeof(float),
                typeof(double),
                typeof(decimal),
                typeof(DateTime),
            }.Contains(t);
        }
    }
    
    0 讨论(0)
  • 2020-12-20 02:03

    I would made as follows:

        void Traverse(Type type, ISet<Type> marks, ICollection<PropertyInfo> result)
        {
            if (marks.Contains(type)) return; else marks.Add(type);
            foreach (var propertyInfo in type.GetProperties())
                if (propertyInfo.PropertyType.IsPrimitive) result.Add(propertyInfo);
                else Traverse(propertyInfo.PropertyType, marks, result);
        }
    

    and

    var props = new List<PropertyInfo>();
    Traverse(yourRootType, new HashSet<Type>(), props);
    
    0 讨论(0)
  • 2020-12-20 02:08

    You need to keep track of types you've already checked.

    public static List<PropertyInfo> ProcessType(Type type)
    {
        return ProcessType(type, new List<Type>());
    }
    public static List<PropertyInfo> ProcessType(Type type, List<Type> processedTypes)
    {
        // Keep track of results
        var result = new List<PropertyInfo>();
    
        // Iterate properties of the type
        foreach (var property in type.GetProperties())
        {
            var propertyType = property.PropertyType;
    
            // If the property has a primitive type
            if (propertyType.IsPrimitive)
            {
                // add it to the results
                result.Add(property);
            }
            // If the property has a non-primitive type
            // and it has not been processed yet
            else if (!processedTypes.Contains(propertyType))
            {
                // Mark the property's type as already processed
                processedTypes.Add(propertyType);
    
                // Recursively processproperties of the property's type
                result.AddRange(ProcessType(propertyType, processedTypes));
            }
        }
    
        return result;
    }
    
    0 讨论(0)
提交回复
热议问题