Bindable Attribute

I am trying to emit a Bindable attribute on given columns for being able to automatically generate columns in a DataGrid control on the client.

I have tried using Bindable(true) and Bindable(false). In the configure method I have added
var nativeTypes = GetPlugin();
nativeTypes.MetadataTypesConfig.ExportAttributes.Add(typeof(System.ComponentModel.BindableAttribute));

The attribute is emitted but never has any values for the attribute just emits [Bindable].

Can you tell me what I am doing wrong?

Derek

ServiceStack won’t be able to emit constructor values, just property values of attributes, it also doesn’t emit property attribute default values.

I’ve looked into improving generating attributes using constructor values in this commit where it should not support generating the [Bindable] attribute constructor values by default.

For other times where the attributes built-in heuristics can’t be inferred, you can now override how the metadata of the Attribute is populated which controls the generated constructor and property values, e.g:

var nativeTypes = GetPlugin<NativeTypesFeature>();
nativeTypes.ExportAttribute<BindableAttribute>(attr => {
    var metaAttr = nativeTypes.GetGenerator().ToMetadataAttribute(attr);//default
    // make modifications to MetadataAttribute Args + ConstructorArgs
    return metaAttr;
});

This change is available from v5.6.1 that’s now available on MyGet.

Thank you for your help. Not trying to be difficult but I was thinking that if someone decorates their classes on the server that the attributes from the dtos.cs should match what they declared. I am still a little new to ServiceStack so I have not played with all of the features. I have code that would copy the attributes and assign them to each property using the CodeAttributeDeclaration with the pertinent CodeAttributeArguments. If there are constructor arguments that are used it assigns those, if there are named arguments assigned it uses those. If you would like to see that let me know.

Hopefully the latest version improves the attribute support, but if you have code that results in better heuristics for re-creating the attribute declaration, sure I’d like to see it. Only thing is that it has to serialize to the MetadataAttribute DTO data structure that all languages use to render the Attributes.

var dispProp = pi.GetCustomAttribute<DisplayAttribute>();
    if (dispProp != null)
    {
        var attribs = CustomAttributeData.GetCustomAttributes(pi).Where(a=>a.AttributeType == typeof(DisplayAttribute));
        foreach(var attrib in attribs)
        {
            var arguments = new List<CodeAttributeArgument>();
            foreach (var argument in attrib.ConstructorArguments)
            {
                arguments.Add(new CodeAttributeArgument(new CodeSnippetExpression(argument.ToString())));
            }

            if (attrib.NamedArguments != null)
                foreach (var argument in attrib.NamedArguments)
                {
                    arguments.Add(new CodeAttributeArgument(new CodeSnippetExpression(argument.ToString())));
                }
            cfield.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference("Display"), arguments.ToArray()));
        }
    }
  1. pi being the PropertyInfo you are getting (not really sure if you are using reflection or some other mechanism).

  2. this is specific for DisplayAttribute but could be used for any custom attribute.

  3. cfield is the CodeTypeReference for the class property.

These are what I have come up with, the other stuff seems to work fine so no suggestions there :wink: Again this suggestion is strictly to emit the attributes assigned in the DTO on the server as designed by the user.

Thanks for listening.

Unfortunately we can’t use CustomAttributeData as ServiceStack supports adding attributes dynamically which aren’t returned by CustomAttributeData.GetCustomAttributes() and there doesn’t seem any reliable way to get the CustomAttributeData from an Attribute instance.