如何获得一个对象的所有原始类型

时间:2011-06-21 11:58:07

标签: c#

我想拥有一个具有原始类型的对象的所有属性,如果该对象与另一个类有关系,我想拥有另一个类的原始属性

问题是如果实体A有实体B而B有A,我该怎么办

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

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

4 个答案:

答案 0 :(得分:7)

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

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

答案 1 :(得分:0)

我在等待建筑工作时很无聊,喜欢你的作业;)

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

答案 2 :(得分:0)

我会做如下:

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

答案 3 :(得分:0)

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

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