Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C#] Support for immutable type definitions #439

Open
Horusiath opened this issue May 2, 2017 · 5 comments
Open

[C#] Support for immutable type definitions #439

Horusiath opened this issue May 2, 2017 · 5 comments

Comments

@Horusiath
Copy link

Right now Bond constraints serialized types to expose default constructor and properties with public getters/setters. One of the possible use cases for bond would be a message-driven systems, where message immutability is highly desired.

It would be great if Bond wouldn't require types to have public default constructors and support readonly fields and properties. A lot of high-perf serializers supports those features i.e. protobuf or Hyperion.

@chwarr
Copy link
Member

chwarr commented May 2, 2017

The gbc C# mode flag --readonly-properties can be used to generate classes with private setters. This still generates a default, parameter-less constructor. It doesn't generate a constructor that takes field values as arguments: unfortunately, you'll still have to write the constructor by hand.

If someone were interested in contributing to codegen to have it generate full constructors, that would be a nice thing to have. I think the design here is that the constructors are behind a flag like --constructors and that flag is incompatible with bond_meta field types.

In our spare time, @ant0nsc and I are working on F# support. Things like annotated records and gbc-based codegen. This has resulted in our doing much of the ground work for immutable, construct-only types. Since this is a spare-time thing for both of us, I can't give you a time line for when it will ship.

There a distinct possibility that the classes generated by --readonly-properties cannot be serialized/deserialized in environments where we cannot access private member via reflection (e.g., some phone environments).

@grant-d
Copy link

grant-d commented May 9, 2017

"write the constructor by hand" - I assume that means we do that in a related partial class.
I remember trying to do that and (unless I did something wrong) it would not compile - it seemed the codegen did not happen in time for VS to accept assignment to IDL fields. If this is expected to work, is there a unit/sample somewhere?

@chwarr
Copy link
Member

chwarr commented May 10, 2017

I don't have a specific example to point you at, but I just got the following to work:

foo.bond

namespace ReadonlyProps;

struct Foo
{
    0: int32 Bar = 45;
    1: string Baz = "hello";
}

foo.cs

namespace ReadonlyProps
{
    using System;
    using System.Diagnostics;

    using Bond;
    using Bond.IO.Safe;
    using Bond.Protocols;

    public partial class Foo
    {
        public Foo(int bar, string baz) : this("", "")
        {
            Bar = bar;
            Baz = baz;
        }
    }

    internal static class Program
    {
        private static void Main()
        {
            var f = new Foo(100, "one hundred");

            var d = SerializeCB(f);

            var f2 = DeserializeCB<Foo>(d);

            Debug.Assert(f.Bar == f2.Bar);
            Debug.Assert(f.Baz == f2.Baz);
        }

        private static ArraySegment<byte> SerializeCB<T>(T obj)
        {
            var output = new OutputBuffer();
            var cbWriter = new CompactBinaryWriter<OutputBuffer>(output);

            var serializer = new Serializer<CompactBinaryWriter<OutputBuffer>>(typeof (T));
            serializer.Serialize(obj, cbWriter);

            return output.Data;
        }

        private static T DeserializeCB<T>(ArraySegment<byte> payload)
        {
            var input = new InputBuffer(payload);
            var cbReader = new CompactBinaryReader<InputBuffer>(input);

            var deserializer = new Deserializer<CompactBinaryReader<InputBuffer>>(typeof (T));
            return deserializer.Deserialize<T>(cbReader);
        }
    }
}

foo.csproj

...
  <ItemGroup>
    <BondCodeGen Include="foo.bond">
      <Options>--readonly-properties</Options>
    </BondCodeGen>
  </ItemGroup>
...

@grant-d
Copy link

grant-d commented Jun 2, 2017

Thanks Chris, that should work fine - appreciate the sample

@bsagal
Copy link

bsagal commented Apr 26, 2020

In order to fully implement immutable types an option is needed to to allow read only collection properties.

There is already an option to use interfaces rather than concrete collection types, maybe an option can be added to use read only collection interfaces or immutable collection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants