Skip to content

stonygrey/StonyGrey.ObjectMapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 

Repository files navigation

StonyGrey.ObjectMapper

StonyGrey.ObjectMapper is a GRPC-aware source generated object mapper. In addition to mapping POCOs, it generates extension methods that map between Protocol Buffers (Protobuf) classes generated by Grpc.Tools and domain classes provided by you.

Given a protobuf definition such as this:

package Protobuf;

enum TestEnum { One = 0; Two = 1; }

message TestMessage {
    string String = 1;
    int32 Int = 2;
    optional int32 Optional = 3;
    int32 NonOptional = 4;
    bytes Guid = 5;
    sint64 DateTime = 6;
    oneof OneOf {
        sint64 OneOfA = 7;
        sint64 OneOfB = 8;
    }
    TestEnum TestEnum = 9;
    bytes Data = 10;
    optional bytes OptionalData = 11;
}

Grpc.Tools will generate a C# class (that is too verbose in nature to include here). The StonyGrey.ObjectMapper will generate extension methods that map between this Grpc.Tools created class and a domain class created by you. For example:

namespace Domain
{
    public enum TestEnum { One, Two }

    public class TestMessage
    {
        public string? String { get; set; }
        public int Int { get; set; }
        public int? Optional { get; set; }
        public int NonOptional { get; set; }
        public long OneOfA { get; set; }
        public long OneOfB { get; set; }
        public DateTime DateTime { get; set; }
        public Guid Guid { get; set; }
        public TestEnum TestEnum { get; set; }
        public byte[] Data { get; set; } = Array.Empty<byte>();
        public byte[]? OptionalData { get; set; }
    }
}

Extension methods in a class annotated with the MappingConversion attribute will convert between incompatible types.

namespace Domain
{
    [MappingConversion]
    public static partial class MappingExtensions
    {
        public static ByteString MapToByteString(this Guid value)
            => ByteString.CopyFrom(value.ToByteArray());

        public static byte[] MapToByteArray(this ByteString value)
            => value == null ? Array.Empty<byte>() : value.ToByteArray();

    ...

    }
}

Usage

Please see the StonyGrey.ObjectMapper.Host project for a working example.

  1. Add the StonyGrey.ObjectMapper Nuget to your project.

  2. Use the Map attribute to define the source and target classes:

     [assembly: Map(typeof(Domain.TestMessage), typeof(Protobuf.TestMessage))]
     [assembly: Map(typeof(Protobuf.TestMessage), typeof(Domain.TestMessage), ContainingNamespaceKind.Destination)]
    
  3. Convert incompatible types in a class annotated with MappingConversion.

StonyGrey.ObjectMapper will generate extension methods with the following signatures:

public static DomainClass Map(this GrpcGeneratedClass self) {...}
public static GrpcGeneratedClass Map(this DomainClass self) {...}

The generated source can be found at YourProject->Dependencies->Analyzers->StonyGrey.ObjectMapper->StonyGrey.ObjectMapper.MapGenerator

Mapping

StonyGrey.ObjectMapper was built to address a specific problem and as such does not cover every scenario. It was tested with proto3 and Grpc.Tools 2.45.0.

Some additional detail on what is or is not supported follows.

Everything is mapped one-to-one with the exception of bytes which is automatically mapped to/ from Google.Protobuf.ByteString.

Conversion is delegated to the caller but can be as simple as a cast.

Message fields that are themselves messages will need MapProtobuf attributes declared. This allows this library to map an entire object graph.

Untested/ Unsupported.

Untested/ Unsupported.

This is supported by relying on the convention that only one of the properties will have a non-default value while all others will have the default value.

Untested/ Unsupported.

C# Types

Mapping between properties is attempted in the following order:

  1. Simple assignment
  2. Conversion using the MappingConversion annotated class.
  3. Map()

The souce must implement IEumerable and the target ICollection.

Acknowledgements

StonyGrey.ObjectMapper is based on the InlineMapping project.

About

.NET Protocol Buffers object mapper source generator

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages