'Getting the name of all DataMembers in a DataContract

I am using WCF service

I have a Data Contract:

[DataContract]
[KnownType(typeof(CustomBranches))]
public class CustomBranches
{
    [DataMember]
    public int Id { get; set; }

    [DataMember]
    public string branch_name { get; set; }

    [DataMember]
    public string address_line_1 { get; set; }

    [DataMember]
    public string city_name { get; set; }
}

Is it possible that i can find the name of all the DataMembers in this class CustomBranches

Like "ID" , "branch name" etc

Thanks



Solution 1:[1]

What you need to do:

  • You don't need to add [KnownType(typeof(CustomBranches))] in your CustomBranches class. A class always knows about itself.
  • You need to filter the properties to only get those with the [DataMember] attribute (nillls' code returned all of them)
  • The data member properties can also be non-public (it works if the serialization is running in full trust)
  • Data members can also be fields (not only properties), so you need to account for them as well.

This is an example of a code which does all of them.

public class StackOverflow_8152252
{
    public static void Test()
    {
        BindingFlags instancePublicAndNot = BindingFlags.Instance |
            BindingFlags.Public |
            BindingFlags.NonPublic;
        var memberNames = typeof(CustomBranches)
            .GetProperties(instancePublicAndNot)
            .OfType<MemberInfo>()
            .Union(typeof(CustomBranches).GetFields(instancePublicAndNot))
            .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute)))
            .Select(x => x.Name);
        Console.WriteLine("All data member names");
        foreach (var memberName in memberNames)
        {
            Console.WriteLine("  {0}", memberName);
        }
    }

    [DataContract]
    public class CustomBranches
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string branch_name { get; set; }

        [DataMember]
        public string address_line_1 { get; set; }

        [DataMember]
        public string city_name { get; set; }

        public int NonDataMember { get; set; }

        [DataMember]
        public string FieldDataMember;

        [DataMember]
        internal string NonPublicMember { get; set; }
    }
}

Solution 2:[2]

I have modified Carlos' answer slightly to ignore data members decorated with a [NonSerialized] attribute:

public class StackOverflow_8152252
{
    public static void Test()
    {
        BindingFlags instancePublicAndNot = BindingFlags.Instance |
            BindingFlags.Public |
            BindingFlags.NonPublic;
        var memberNames = typeof(CustomBranches)
            .GetProperties(instancePublicAndNot)
            .OfType<MemberInfo>()
            .Union(typeof(CustomBranches).GetFields(instancePublicAndNot))
            .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute))
                     && !Attribute.IsDefined(x, typeof(NonSerializedAttribute)))
            .Select(x => x.Name);
        Console.WriteLine("All data member names");
        foreach (var memberName in memberNames)
        {
            Console.WriteLine("  {0}", memberName);
        }
    }

    [DataContract]
    public class CustomBranches
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        [NonSerialized]
        public string NonSerializedDataMember { get; set; }
    }
}

Solution 3:[3]

In my case I had several properties with custom data member names defined like this:

[DataMember(Name = "alternate_name")]

I've modified mbonness' answer to return the custom names when present, or the default property names otherwise.

public class StackOverflow_8152253
{
    public static void Test()
    {
        BindingFlags instancePublicAndNot = BindingFlags.Instance |
            BindingFlags.Public |
            BindingFlags.NonPublic;
        var memberNames = typeof(CustomBranches)
            .GetProperties(instancePublicAndNot)
            .OfType<MemberInfo>()
            .Union(typeof(CustomBranches).GetFields(instancePublicAndNot))
            .Where(x => Attribute.IsDefined(x, typeof(DataMemberAttribute))
                     && !Attribute.IsDefined(x, typeof(NonSerializedAttribute)))
            .Select(x => x.CustomAttributes.FirstOrDefault(a => a.AttributeType == typeof(DataMemberAttribute))?.NamedArguments.FirstOrDefault(n => n.MemberName == "Name").TypedValue.Value ?? x.Name);
        Console.WriteLine("All data member names");
        foreach (var memberName in memberNames)
        {
            Console.WriteLine("  {0}", memberName);
        }
    }

    [DataContract]
    public class CustomBranches
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember(Name = "alternate_name")]
        public string PropertyWithAlternateName { get; set; }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JohnD
Solution 2 mbonness
Solution 3