13 KiB
C# code generator for AutoRest V3
Setup
- NodeJS (13.x.x)
npm install
(at root)- .NET Core SDK (3.0.100)
- PowerShell Core
- Java (for V2 testserver)
Build
dotnet build
(at root)./eng/Generate.ps1
(at root in PowerShell Core)
Test
dotnet test
(at root)
Customizing the generated code
- Make a model internal
- Rename a model class
- Make model property internal
- Rename a model property
- Change a model property type
- Changing member doc comment
- Customize serialization/deserialization methods
- Renaming an enum
- Renaming an enum member
- Make a client internal
- Rename a client
- Replace any generated member
- Remove any generated member
Make a model internal
Define a class with the same namespace and name as generated model and use the desired accessibility.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model { }
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
internal partial class Model { }
}
Generated code after (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
- public partial class Model { }
+ internal partial class Model { }
}
Rename a model class
Define a class with a desired name and mark it with [CodeGenModel("OriginalName")]
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model { }
}
Add customized model (NewModelClassName.cs)
namespace Azure.Service.Models
{
[CodeGenModel("Model")]
public partial class NewModelClassName { }
}
Generated code after (Generated/Models/NewModelClassName.cs):
namespace Azure.Service.Models
{
- public partial class Model { }
+ public partial class NewModelClassName { }
}
Make model property internal
Define a class with a property matching a generated property name but with desired accessibility.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
public string Property { get; }
}
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
public partial class Model
{
internal string Property { get; }
}
}
Generated code after (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
- public string Property { get; }
}
}
Rename a model property
Define a partial class with a new property name and mark it with [CodeGenMember("OriginalName")]
attribute.
NOTE: you can also change a property to a field using this mapping.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
public string Property { get; }
}
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
public partial class Model
{
[CodeGenMember("Property")]
public string RenamedProperty { get; }
}
}
Generated code after (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
- public string Property { get; }
+ // All original Property usages would reference a RenamedProperty
}
}
Change a model property type
⚠️
NOTE: This is supported for a narrow set of cases where the underlying serialized type doesn't change
Scenarios that would work:
- String <-> TimeSpan (both represented as string in JSON)
- Float <-> Int (both are numbers)
- String <-> Enums (both strings)
Won't work:
- String <-> Bool (different json type)
- Changing model kinds
If you think you have a valid re-mapping scenario that's not supported file an issue.
⚠️
Define a property with different type than the generated one.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
public string Property { get; }
}
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
public partial class Model
{
public DateTime Property { get; }
}
}
Generated code after (Generated/Models/Model.Serializer.cs):
namespace Azure.Service.Models
{
public partial class Model
{
- public string Property { get; }
+ // Serialization code now reads and writes DateTime value instead of string
}
}
Changing member doc comment
Redefine a member in partial class with a new doc comment.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
/// Subpar doc comment
public string Property { get; }
}
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
public partial class Model
{
/// Great doc comment
public string Property { get; }
}
}
Generated code after (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
- /// Subpar doc comment
- public string Property { get; }
}
}
Customize serialization/deserialization methods
Use the Replace any generated member approach to replace Serialize/Deserialize method with a custom implementation.
Generated code before (Generated/Models/Cat.Serialization.cs):
namespace Azure.Service.Models
{
public partial class Cat
{
internal static Cat DeserializeCat(JsonElement element)
{
string color = default;
string name = default;
foreach (var property in element.EnumerateObject())
{
if (property.NameEquals("color"))
{
if (property.Value.ValueKind == JsonValueKind.Null)
{
continue;
}
color = property.Value.GetString();
continue;
}
if (property.NameEquals("name"))
{
if (property.Value.ValueKind == JsonValueKind.Null)
{
continue;
}
name = property.Value.GetString();
continue;
}
}
return new Cat(id, name);
}
}
}
Add customized model (Cat.cs)
namespace Azure.Service.Models
{
public partial class Cat
{
internal static Cat DeserializeCat(JsonElement element)
{
string color = default;
string name = default;
foreach (var property in element.EnumerateObject())
{
if (property.NameEquals("name"))
{
if (property.Value.ValueKind == JsonValueKind.Null)
{
continue;
}
name = property.Value.GetString();
continue;
}
}
// WORKAROUND: server never sends color, default to black
color = "black";
return new Cat(name, color);
}
}
}
Generated code after (Generated/Models/Model.cs):
Generated code won't contain the DeserializeCat method and the custom one would be used for deserialization.
Renaming an enum
Redefine an enum with a new name and all the members mark it with [CodeGenModel("OriginEnumName")]
.
NOTE: because enums can't be partial all values have to be copied
Generated code before (Generated/Models/Colors.cs):
namespace Azure.Service.Models
{
public enum Colors
{
Red,
Green,
Blue
}
}
Add customized model (WallColors.cs)
namespace Azure.Service.Models
{
[CodeGenModel("Colors")]
public enum WallColors
{
Red,
Green,
Blue
}
}
Generated code after (Generated/Models/Model.cs):
-namespace Azure.Service.Models
-{
- public enum Colors
- {
- Red,
- Green,
- Blue
- }
-}
+// Serialization code uses the new WallColors type name
Renaming an enum member
Redefine an enum with the same name and all the members, mark renamed member with [CodeGenMember("OriginEnumMemberName")]
.
NOTE: because enums can't be partial all values have to be copied but only the ones being renamed should be marked with an attributes
Generated code before (Generated/Models/Colors.cs):
namespace Azure.Service.Models
{
public enum Colors
{
Red,
Green,
Blue
}
}
Add customized model (Colors.cs)
namespace Azure.Service.Models
{
public enum Colors
{
Red,
Green,
[CodeGenMember("Blue")]
SkyBlue
}
}
Generated code after (Generated/Models/Model.cs):
-namespace Azure.Service.Models
-{
- public enum Colors
- {
- Red,
- Green,
- Blue
- }
-}
+// Serialization code uses the new SkyBlue member name
Make a client internal
Define a class with the same namespace and name as generated client and use the desired accessibility.
Generated code before (Generated/Operations/ServiceClient.cs):
namespace Azure.Service.Operations
{
public partial class ServiceClient { }
}
Add customized model (Model.cs)
namespace Azure.Service.Operations
{
internal partial class ServiceClient { }
}
Generated code after (Generated/Operations/ServiceClient.cs):
namespace Azure.Service.Operations
{
- public partial class ServiceClient { }
+ internal partial class ServiceClient { }
}
Rename a client
Define a partial client class with a new name and mark it with [CodeGenClient("OriginalName")]
Generated code before (Generated/Operations/ServiceClient.cs):
namespace Azure.Service.Operations
{
public partial class ServiceClient {}
}
Add customized model (Model.cs)
namespace Azure.Service.Operations
{
[CodeGenClient("ServiceClient")]
public partial class TableClient { }
}
Generated code after (Generated/Operations/ServiceClient.cs):
namespace Azure.Service.Operations
{
- public partial class ServiceClient { }
+ public partial class TableClient { }
}
Replace any generated member
Works for model and client properties, methods, constructors etc.
Define a partial class with member with the same name and for methods same parameters.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
public Model()
{
Property = "a";
}
public string Property { get; set; }
}
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
public partial class Model
{
internal Model()
{
Property = "b";
}
}
}
Generated code after (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
- public Model()
- {
- Property = "a";
- }
}
}
Remove any generated member
Works for model and client properties, methods, constructors etc.
Define a partial class with [CodeGenSuppress("NameOfMember", typeof(Parameter1Type), typeof(Parameter2Type))]
attribute.
Generated code before (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
public Model()
{
Property = "a";
}
public Model(string property)
{
Property = property;
}
public string Property { get; set; }
}
}
Add customized model (Model.cs)
namespace Azure.Service.Models
{
[CodeGenSuppress("Model", typeof(string))]
public partial class Model
{
}
}
Generated code after (Generated/Models/Model.cs):
namespace Azure.Service.Models
{
public partial class Model
{
- public Model(string property)
- {
- Property = property;
- }
}
}
Configuration
# autorest-core version
version: 3.0.6282
shared-source-folder: $(this-folder)/src/assets
save-inputs: true
use: $(this-folder)/artifacts/bin/AutoRest.CSharp.V3/Debug/netcoreapp3.0/
clear-output-folder: false
pipeline:
csharpproj:
input: modelerfour/identity
csharpproj/emitter:
input: csharpproj
scope: output-scope