Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow parameter type name to be specified for WriteCodeFragment task (#…
…6285) Fixes #2281 Context This change allows the WriteCodeFragment task to define assembly attributes that require parameters that are not of type System.String. For example, CSLCompliantAttribute can be generated with a parameter of true instead of "true". Changes Made Additional metadata can be defined on an AssemblyAttribute that specifies how to treat the parameters specified in the metadata. There are three different ways that the parameters can be treated. Infer the Type Without specifying any additional metadata, attributes that are defined in the mscorlib assembly (i.e. types that can be loaded via System.Type.GetType(string)) will have their parameter types inferred by finding the constructor where the parameter count matches the number of parameters specified in the metadata. For example, this: <ItemGroup> <AssemblyAttribute Include="CLSCompliantAttribute"> <_Parameter1>true</_Parameter1> </AssemblyAttribute> </ItemGroup> Will produce the code: [assembly: CLSCompliantAttribute(true)] For backward-compatibility, if the attribute cannot be found, or no matching constructor is found, the parameter is treated as a string. Declare the Type An additional metadata item can be used to specify the full name of the parameter type. To do this, add a metadata item that has the same name as the parameter with "_TypeName" appended to the end. For example, this: <ItemGroup> <AssemblyAttribute Include="TestAttribute"> <_Parameter1>True</_Parameter1> <_Parameter1_TypeName>System.Boolean</_Parameter1_TypeName> </AssemblyAttribute> </ItemGroup> Will produce the code: [assembly: TestAttribute(true)] This also works with named parameters: <ItemGroup> <AssemblyAttribute Include="TestAttribute"> <Foo>42</IdentifyLevel> <Foo_TypeName>System.Int32</Foo_TypeName> </AssemblyAttribute> </ItemGroup> [assembly: TestAttribute(42)] All types that can be used as attribute parameters are supported, except for arrays. For backward-compatibility, if a metadata item ends with "_TypeName", but there is no metadata item for the parameter with that name, then it will be treated as another named property. For example, this: <ItemGroup> <AssemblyAttribute Include="TestAttribute"> <Foo_TypeName>System.Int32</Foo_TypeName> </AssemblyAttribute> </ItemGroup> Would produce the code: [assembly: TestAttribute(Foo_TypeName="System.Int32")] Specify the Exact Code For cases where declaring the type is insufficient (such as when the parameter is an array), you can specify the exact that that will be generated for the parameter by adding metadata that has the same name as the parameter with "_IsLiteral" appended to the end. For example, this: <ItemGroup> <AssemblyAttribute Include="TestAttribute"> <_Parameter1>new int[] { 1, 3, 5 } /* odd numbers */</_Parameter1> <_Parameter1_IsLiteral>true</_Parameter1_IsLiteral> </AssemblyAttribute> </ItemGroup> Will produce the code: [assembly: TestAttribute(new int[] { 1, 3, 5 } /* odd numbers */)] The limitation with this is that the code you provide is language-specific. For example, the literal value in the metadata above will only work in C#. If you used that same metadata in a VB.NET project, you would receive a compiler error. This works with both positional and named parameters. As with the ..._TypeName metadata, if an ..._IsLiteral metadata does not have a corresponding parameter name, it will be treated as a named parameter for backward-compatibility. Mixed Parameter Behavior Because the additional metadata only applies to a specific parameter, you can choose to treat different parameters in different ways. For example, you can infer/use the default behavior for one parameter, specify the type for the second parameter and use a literal value for the third. For example: <ItemGroup> <AssemblyAttribute Include="TestAttribute"> <_Parameter1>This is a string</_Parameter1> <_Parameter2>42></Parameter2> <_Parameter2_TypeName>System.Int32</_Parameter2_TypeName> <_Parameter3>new int[] { 1 }</_Parameter3> <_Parameter3_IsLiteral>true</_Parameter3_IsLiteral> </AssemblyAttribute> </ItemGroup>
- Loading branch information