Shaggydog
Shaggydog

Reputation: 3788

Complex attribute declaration for methods in CodeDom

I'm trying to generate some methods using CodeDom, I have a problem generating custom attributes for these methods.

I can manage simple empty attributes, such as

[DataMember()]

or attributes with string value arguments,

[DataContract(Namespace = "http://somenamespace")]

But there are more complex attributes I need to generate, such as

[WebInvoke(Method = "POST", UriTemplate = "SomeTemplate", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]

and

[FaultContract(typeof(Collection<MyFault>))]

For the arguments with enum values ResponseFormat = WebMessageFormat.Json I've tried similar approach to what I did for strings, creating a CodePrimitiveExpression instance:

CodeAttributeDeclaration webInvoke = new CodeAttributeDeclaration()
{

    Name = "WebInvoke",
    Arguments =
            {
                new CodeAttributeArgument
                {
                    Name = "Method",
                    Value = new  CodePrimitiveExpression("POST")
                },
                new CodeAttributeArgument
                {
                    Name = "UriTemplate",
                    Value = new  CodePrimitiveExpression(method.Name)
                },
                 new CodeAttributeArgument
                {
                    Name = "RequestFormat",
                    Value = new CodePrimitiveExpression(WebMessageFormat.Json)
                },
                  new CodeAttributeArgument
                {
                    Name = "ResponseFormat",
                    Value = new  CodePrimitiveExpression(WebMessageFormat.Json)
                }
            }
};

However, this does not work, I get an exception saying

Invalid Primitive Type: System.ServiceModel.Web.WebMessageFormat. Consider using CodeObjectCreateExpression.

I did consider using CodeObjectCreateExpression, but I don't know how. It expects either a string or a CodeTypeReference, and as a second parameter an array of CodeExpression parameters. I have no idea what parameters to put there.

As for the other attribute, the one with typeof(Colleciton<MyFault>), I don't even know where to start. Any help would be appreciated.

EDIT: Someone suggested I call CustomAttributeData.GetCustomAttributes on the methods I'm trying to mimic, so I did that. For the sake of efficiency and clarity, I'll provide the data in a screenshot. This gave me a somewhat better idea of what I'm dealing with, but I'm still unsure about how to implement it. enter image description here

Upvotes: 4

Views: 1547

Answers (1)

svick
svick

Reputation: 244767

Expressions like WebMessageFormat.Json look like accessing a static field, so that's how you have to write it:

new CodeAttributeArgument
{
    Name = "RequestFormat",
    Value = new CodeFieldReferenceExpression(
        new CodeTypeReferenceExpression("WebMessageFormat"), "Json")
}

The typeof expression is a special type of expression, so it has its own CodeDOM type:

new CodeAttributeDeclaration(
    "FaultContract",
    new CodeAttributeArgument(new CodeTypeOfExpression("Collection<MyFault>")))

To see the list of all expression types available in CodeDOM, look at the inheritance hierarchy in the docs of CodeExpression.

Upvotes: 3

Related Questions