簡體   English   中英

.Net 反射以獲取具有自定義屬性的嵌套屬性

[英].Net reflection to get nested property with custom attribute

我想知道使用嵌套 class 的自定義屬性名稱反射來獲取道具信息和值的最佳方法。 使用下面的代碼,我可以通過遞歸獲取道具信息。 但是有沒有更好的方法或使用 LINQ。 請注意,我不想將 class 類型硬編碼為類似於其他解決方案

我也想通過自定義屬性獲取屬性值

例如 var propValue =?????

 public class PlanetRoot

    {

        public void GetNeighborMoon()

        {

            Planet planet = new Planet();

            Product product = new Product();

            Neighbor neighbor = new Neighbor();

            neighbor.Moons = 10;

            neighbor.RingColor = "Red";

            product.Neighbors = new List<Neighbor>();

            product.Neighbors.Add(neighbor);

            planet.Product = product;



            //1. Get the RingColor property info of neighbor with attribute MyDBField(Name = "NeighborRing") . Is there a better way

            PropertyInfo propInfo = null;
            DoRecursiveGetProperty(planet.GetType(), "NeighborRing", out propInfo );



            //2. Get the RingColor property value of neighbor with attribute MyDBField(Name = "NeighborRing")

            //var propValue = GetPropertyValue(????);

        }

    }



    private static PropertyInfo DoRecursiveGetProperty(Type type, string attribName, out PropertyInfo propInfo)

    {

        PropertyInfo[] pi = type.GetProperties();

        propInfo= null;

        foreach (PropertyInfo p in pi)

        {

            var dbFieldAttribute = (MyDBFieldAttribute)Attribute.GetCustomAttribute(p, typeof(MyDBFieldAttribute));

            if (dbFieldAttribute != null && attribName.ToUpper() == dbFieldAttribute.Name.ToUpper())

            {

                propInfo= p;

                //Console.WriteLine(p.Name + " : " + (dbFieldAttribute != null && dbFieldAttribute.Name != null ? dbFieldAttribute.Name : "****"));

                return true;

            }



            if (p.PropertyType.IsClass && !p.PropertyType.IsValueType && !p.PropertyType.IsPrimitive

            && p.PropertyType.FullName != "System.String")
                if (propInfo != null) return true;
                else DoRecursiveGetProperty(p.PropertyType, attribName, out propInfo);



        }



        return false;



    }

    public class Planet

    {

        public string PlanetId { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public Product Product { get; set; }



        [MyDBField(Name="PubDate")]

        public string Publishdate { get; set; }



    }



    public class Product

    {

        public string ProductId { get; set; }

        public List<Neighbor> Neighbors { get; set; }



    }



    public class Neighbor

    {

        [MyDBField(Name = "NeighborRing")]

        public string RingColor { get; set; }

        public int Moons { get; set; }

    }



    public class MyDBFieldAttribute : System.Attribute

    {

        public string Name { get; set; }

    }

為了獲取可能在集合中的嵌套成員的值,您需要迭代 collections,並跟蹤當前的 object。

假設您由於其他原因不需要生成的PropInfo ,只需嘗試獲取該值:

private static bool TryRecursiveGetValueWithMyDBFieldName(object startObject, string attribName, out object propValue) {
    PropertyInfo[] pi = startObject.GetType().GetProperties();

    foreach (PropertyInfo p in pi) {
        var dbFieldAttribute = (MyDBFieldAttribute)Attribute.GetCustomAttribute(p, typeof(MyDBFieldAttribute));
        if (dbFieldAttribute != null && dbFieldAttribute.Name.Equals(attribName, StringComparison.CurrentCultureIgnoreCase)) {
            //Console.WriteLine(p.Name + " : " + (dbFieldAttribute != null && dbFieldAttribute.Name != null ? dbFieldAttribute.Name : "****"));
            propValue = p.GetValue(startObject);
            return true;
        }

        if (p.PropertyType.IsClass && !p.PropertyType.IsValueType && !p.PropertyType.IsPrimitive &&
            !p.PropertyType.FullName.StartsWith("System.")) {
            var tryObject = p.GetValue(startObject);
            if (tryObject != null && TryRecursiveGetValueWithMyDBFieldName(tryObject, attribName, out propValue))
                return true;
        }

        if (p.PropertyType.IsClass && p.GetValue(startObject) is IEnumerable ip) {
            foreach (var obj in ip) {
                if (obj != null && TryRecursiveGetValueWithMyDBFieldName(obj, attribName, out propValue))
                    return true;
            }
        }
    }

    propValue = default;
    return false;
}

要使用它,請使用初始 object 調用:

var foundAttrib = TryRecursiveGetValueWithMyDBFieldName(planet, "NeighborRing", out var propValue);

注意:這將返回具有匹配屬性的第一個 object 的值,例如, List<Neighbor>成員的每個成員都將具有MyDBField屬性和NeighborRingName屬性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM