如何获取对象的所有基元类型

本文关键字:类型 何获 取对象 | 更新日期: 2023-09-27 17:59:41

我想拥有一个具有基元类型的对象的所有属性,如果该对象与另一个类有关系,我也想拥有另一个类别的基元属性

问题是,如果实体A有实体B,而实体B有A,我能做什么

在简单的情况下,通过使用反射,我可以获得第一级Primitive属性,但我不能进入实体B并再次获得A的Primitive性质,将创建一个循环,你提供了什么?

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;}
}

如何获取对象的所有基元类型

您可以跟踪访问的类型以避免递归:

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);
    }
}

我在等待构建时感到无聊,祝你的家庭作业愉快;)

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);
            }
        }
    }
}

我会做如下:

    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);
    }

var props = new List<PropertyInfo>();
Traverse(yourRootType, new HashSet<Type>(), props);

您需要跟踪已检查的类型。

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;
}