Is there a way to decorate multiple properties with DataMember in a data contract in WCF?

1.2k views Asked by At

I've got a basic WCF service. I've split out my data contracts and one of them is a class with a large amount of public properties. If I want to make these properties available to the client I'm assuming all of these will need to have [DataMember]. So, as there's a large number of these properties, is there any way of bulk decorating them with [DataMember]? something like:

[DataMember]
(
    public string Title { get; set; }
    public Guid ID { get; set; }
    public Description { get; set; }

    //more properties...
)

I've only ever seen:

[DataMember]
public string Title { get; set; }
[DataMember]
public Guid ID { get; set; }
[DataMember]
public Description { get; set; }
2

There are 2 answers

4
Max Brodin On BEST ANSWER

No, unfortunately, it's not possible to mark the group of properties with the attribute.

0
Raghu Reddy Muttana On

Yes. You can use Aspect Oriented Programming technique for this. Here is the solution when you use PostSharp. PostSharp can be installed via nuget (postsharp express is free).

You need to write an aspect first. See the code below.

namespace AspectOrientedProgramming
{
 [Serializable]
    [MulticastAttributeUsage (MulticastTargets.Class)]
    public sealed class DataContractAspect:TypeLevelAspect, IAspectProvider
    {
        public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
        {
            var targetType = (Type) targetElement;

            var introduceDataContractAspect =
                new CustomAttributeIntroductionAspect(
                    new ObjectConstruction(typeof(DataContractAttribute).GetConstructor(Type.EmptyTypes)));
            var introduceDataMemberAspect =
                new CustomAttributeIntroductionAspect(
                    new ObjectConstruction(typeof(DataMemberAttribute).GetConstructor(Type.EmptyTypes)));

            yield return new AspectInstance(targetType, introduceDataContractAspect);

            foreach (var property in targetType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance))
            {
                if (property.CanWrite && !property.IsDefined(typeof(NotADataMemberAttribute), false))
                {
                    yield return new AspectInstance(property, introduceDataMemberAspect);
                }
            }
        }
    }
}

Now create a Not a datamember attribute.

 [AttributeUsage(AttributeTargets.Property)]

    public sealed class NotADataMemberAttribute:Attribute
    {

    }

Decorate those few properties that you don't want to be DataMembers with [NotADataMember].

Add the following line in AssemblyInfo.cs file. Replace YourNameSpaces with appropriate to your project specific.

[assembly: DataContractAspect(AttributeTargetTypes = "YourNamespaces.DataContracts.*")]

Thats it.

With this approach, You don't have to decorate every member with DataMember attribute. Also, you don't have to decorate every class with DataContract.