Search code examples
c#custom-attributescallermembername

CallerMemberName doesn't work for Attribute constructor on a field


I'm producing a serializer in C# (.NET 4.5, VS 2013), and I'm using an attribute to control serialization metadata, such as the name to store a member under for reading and writing. Since I don't want to write out the member name as an argument for the attribute each time, I'm trying to use CallerMemberName.

For properties, it works fine: the property name is passed when the constructor gets called, and the attribute lets me assign the property value in deserialization.

For fields, for whatever reason, CallerMemberName refuses to work. Instead, I'm getting the default string.Empty every time, even when the other argument parameters are passing correctly.

My current code for testing this is:

class AttributeTest
{
    [VariableAttribute(true)]
    public string testField;

    [VariableAttribute(false)]
    public string testProperty { get; set; }

    static void Main(string[] args)
    {
        Console.WriteLine("spawning");
        AttributeTest test = new AttributeTest();
        test.testField = "sdasd";
        foreach (MemberInfo info in typeof (AttributeTest).GetMembers().Where(x => x.GetCustomAttribute(typeof(VariableAttribute)) != null))
        {

            //Console.WriteLine(info.Name);
            VariableAttribute attr = (VariableAttribute)info.GetCustomAttribute(typeof (VariableAttribute));
            Console.WriteLine(attr.testStore);
        }

        //Console.WriteLine(typeof(AttributeTest).GetMember("testField")[0].GetCustomAttributes().ElementAt(0));

        test.testProperty = "falsdka";
        Console.ReadKey();
    }
}

[AttributeUsage(AttributeTargets.Field|AttributeTargets.Property)]
public class VariableAttribute : System.Attribute
{
    public bool testStore;

    public VariableAttribute(bool test = true, [CallerMemberName] string caller = "")
    {
        testStore = test;
        Console.WriteLine(caller);
    }
}

I've tested it with the field receiving no arguments, with the field receiving an argument to make sure the constructor is being called, with the field throwing a constructor exception to make doubly sure the constructor is being called, and I can't figure out what I'm doing wrong.


Solution

  • As MSDN states, quote:

    Allows you to obtain the method or property name of the caller to the method.

    So you'll have to find another way to do what you're doing, or stick with properties.