문제

I would like to define a custom attribute for specific properties of a class. Based on reflection it should be possible to check if the property is annotated with this attribute or not. The first Assert.AreEqual(2, infos.Length) passes but the second Assert.AreEqual(1, properties.Count) fails with properties.Count = 0. What am I missing?

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Reflection;

namespace Test.UnitTesting.Rest.ParameteterModels
{
    public class IncludableAttribute : Attribute
    {
    }

    public class TestClass
    {
        [Includable]
        public List<string> List1 { get; set; }

        public List<string> List2 { get; set; }

        public TestClass()
        {

        }
    }


    [TestClass]
    public class IncludeParamaterModelTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            List<string> properties = new List<string>();

            FieldInfo[] infos = typeof(TestClass).GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
            Assert.AreEqual(2, infos.Length);

            foreach (FieldInfo fi in infos)
            {
                if (fi.IsDefined(typeof(IncludableAttribute), true)) properties.Add(fi.Name);
            }
            Assert.AreEqual(1, properties.Count);
        }
    }
}

This question is similar to C# Reflection : Finding Attributes on a Member Field

도움이 되었습니까?

해결책 2

Your attribute is being applied to the properties. While you do have fields, they're created by the compiler - and your custom attribute isn't being applied to them. Your code is broadly equivalent to:

[CompilerGenerated]
private List<string> list1;

[Includable]
public List<string> List1 { get { return list1; } set { list1 = value; } }

[CompilerGenerated]
private List<string> list2;
public List<string> List2 { get { return list2; } set { list2 = value; } }

As you can see, there are still two fields (list1 and list2) - which is why your first assertion succeeds. However, neither of those have the Includable attribute. It's the List1 property which does.

So you need to be asking for the properties rather than the fields. I'd also do this with LINQ rather than looping explicitly:

var properties = typeof(TestClass)
                     .GetProperties(BindingFlags.NonPublic | 
                                    BindingFlags.Public | 
                                    BindingFlags.Instance)
                     .Where(p => p.IsDefined(typeof(IncludableAttribute), true)
                     .ToList();

(You may want to consider whether you really want to pick up non-public properties.)

다른 팁

You need to use GetProperties instead of GetFields because you do not have any fields in TestClass, you have two auto-implemented properties.And BindingFlags.NonPublic flag seems unnecessary because your properties are defined as public.

var infos = typeof(TestClass)
            .GetProperties(BindingFlags.Public | 
                           BindingFlags.Instance);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top