Skip to content

C#

Bufrnix provides comprehensive C# code generation support for Protocol Buffers, including gRPC services, with full .NET integration.

{
languages.csharp = {
enable = true;
namespace = "MyApp.Protos";
targetFramework = "net8.0";
};
}
  • ✅ Protocol Buffers 3 support
  • ✅ gRPC service generation
  • ✅ .NET 8.0+ support
  • ✅ NuGet package generation
  • ✅ Project file generation
  • ✅ Nullable reference types
  • ✅ JSON serialization support
OptionTypeDefaultDescription
enableboolfalseEnable C# code generation
sdkpackagepkgs.dotnetCorePackages.sdk_8_0.NET SDK to use
outputPathstring"gen/csharp"Output directory for generated code
namespacestring""Base namespace for generated code
targetFrameworkstring"net8.0".NET target framework
langVersionstring"latest"C# language version
nullablebooltrueEnable nullable reference types
generateProjectFilebooltrueGenerate .csproj file
projectNamestring"GeneratedProtos"Name for generated project

Enable gRPC code generation:

{
languages.csharp = {
enable = true;
namespace = "MyApp.Services";
grpc.enable = true;
};
}
OptionTypeDefaultDescription
grpc.enableboolfalseEnable gRPC code generation
grpc.grpcVersionstring"2.72.0"Grpc.Net.Client version
grpc.grpcCoreVersionstring"2.72.0"Grpc.Core.Api version
grpc.generateClientFactoryboolfalseGenerate client factory classes
grpc.generateServerBaseboolfalseGenerate server base implementations
flake.nix
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
bufrnix.url = "github:bufrnix/bufrnix";
};
outputs = { self, nixpkgs, bufrnix }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
packages.${system}.default = bufrnix.lib.mkBufrnixPackage {
inherit (pkgs) lib;
inherit pkgs;
config = {
root = ./proto;
languages.csharp = {
enable = true;
namespace = "MyApp.Models";
generatePackageOnBuild = true;
packageId = "MyApp.Protos";
packageVersion = "1.0.0";
};
};
};
};
}
{
languages.csharp = {
enable = true;
namespace = "MyApp.Services";
grpc = {
enable = true;
generateClientFactory = true;
};
};
}
{
languages.csharp = {
enable = true;
namespace = "Enterprise.Protos";
targetFramework = "net8.0";
langVersion = "12.0";
nullable = true;
# Custom file extension
fileExtension = ".g.cs";
# Assembly info generation
generateAssemblyInfo = true;
assemblyVersion = "1.0.0.0";
# NuGet package settings
generatePackageOnBuild = true;
packageId = "Enterprise.Protos";
packageVersion = "2.1.0";
# Custom protobuf version
protobufVersion = "3.31.0";
# gRPC with custom options
grpc = {
enable = true;
options = ["internal_access"];
generateServerBase = true;
};
};
}

The C# module generates:

gen/csharp/
├── MyMessage.cs # Message classes
├── MyService.cs # Service base classes (if gRPC enabled)
├── MyServiceGrpc.cs # gRPC client/server stubs
└── GeneratedProtos.csproj # Project file (if enabled)

After building the package, run the generated script to create the protobuf files:

Terminal window
# Build the package
nix build
# Generate the protobuf code
./result/bin/bufrnix

This will create the generated C# files in the gen/csharp/ directory according to your configuration.

using Google.Protobuf;
using MyApp.Protos;
var message = new MyMessage
{
Id = 123,
Name = "Example"
};
// Serialize to bytes
byte[] bytes = message.ToByteArray();
// Serialize to JSON
string json = JsonFormatter.Default.Format(message);
using Grpc.Core;
using MyApp.Services;
public class GreeterService : Greeter.GreeterBase
{
public override Task<HelloReply> SayHello(
HelloRequest request,
ServerCallContext context)
{
return Task.FromResult(new HelloReply
{
Message = $"Hello {request.Name}"
});
}
}
using Grpc.Net.Client;
using MyApp.Services;
using var channel = GrpcChannel.ForAddress("http://localhost:5000");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
new HelloRequest { Name = "World" });
  1. Project Structure: The generated .csproj file includes all necessary NuGet references
  2. Namespace Convention: Use dot-separated namespaces matching your project structure
  3. Performance: Enable generatePackageOnBuild for faster builds in CI/CD
  4. Compatibility: Target framework should match your application’s framework
{
  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
    bufrnix = {
      url = "github:conneroisu/bufrnix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = {
    nixpkgs,
    flake-utils,
    bufrnix,
    ...
  }:
    flake-utils.lib.eachDefaultSystem (
      system: let
        pkgs = nixpkgs.legacyPackages.${system};

        # Generate protobuf code
        protoGen = bufrnix.lib.mkBufrnixPackage {
          inherit pkgs;

          config = {
            root = ./proto;
            languages = {
              csharp = {
                enable = true;
                namespace = "ExampleProtos";
                generateProjectFile = true;
                projectName = "ExampleProtos";
              };
            };
          };
        };

        # Build the C# application
        app = pkgs.buildDotnetModule {
          pname = "csharp-proto-example";
          version = "1.0.0";

          src = ./.;

          projectFile = "CSharpExample.csproj";
          nugetDeps = ./deps.nix;

          dotnet-sdk = pkgs.dotnetCorePackages.sdk_8_0;
          dotnet-runtime = pkgs.dotnetCorePackages.runtime_8_0;
        };
      in {
        packages = {
          default = protoGen;
          proto = protoGen;
          inherit app;
        };

        apps.app = {
          type = "app";
          program = "${app}/bin/CSharpExample";
        };

        devShells.default = pkgs.mkShell {
          buildInputs = with pkgs; [
            dotnetCorePackages.sdk_8_0
            protobuf
            grpc
          ];

          shellHook = ''
            echo "C# Proto Example Development Shell"
            echo "Run 'nix run' to generate proto code"
            echo "Run 'nix run .#app' or 'dotnet run' to run the application"
          '';
        };
      }
    );
}