且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用 protobuf 序列化 F# 区分联合

更新时间:2022-03-05 02:44:05

我已经使用了你非常有用的生成输出,看起来基本上一切正常 - except Message.MessageA 子类型.这些几乎有效——它们本质上与自动元组"代码(匹配所有成员的构造函数)相同,除了自动元组当前不适用于子类型.

I've played with your very helpful generated output, and it looks like basically everything works - except the Message.MessageA sub-types. These very nearly work - they are essentially the same as the "auto-tuple" code (a constructor that matches all members), except that auto-tuples doesn't currently apply to sub-types.

认为应该可以通过扩展自动元组代码在这种情况下工作来调整代码以自动工作(我正在尝试考虑任何可能的不良副作用其中,但我没有看到任何).我没有具体的时间框架,因为我需要在多个项目和全职日常工作、家庭和志愿者工作以及(等等)之间平衡时间.

I think it should be possible to tweak the code to work automatically, by extending the auto-tuple code to work in this scenario (I'm trying to think of any possible bad side-effects of that, but I'm not seeing any). I don't have a specific time-frame, as I need to balance time between multiple projects and a full-time day-job, and a family, and volunteer work, and (etc etc).

在短期内,以下 C# 足以使其工作,但我不认为这将是一个有吸引力的选择:

In the short term, the following C# is sufficient to make it work, but I don't expect this will be an attractive option:

RuntimeTypeModel.Default[typeof(Message).GetNestedType("MessageA")]
                .Add("item").UseConstructor = false;
RuntimeTypeModel.Default[typeof(Message).GetNestedType("MessageB")]
                .Add("item").UseConstructor = false;

顺便说一句,这里的属性没有帮助,应该避免:

As an aside, the attributes here are unhelpful and should be avoided:

| [<ProtoMember(1)>] MessageA of MessageA
| [<ProtoMember(2)>] MessageB of MessageB

如果他们做了任何事情,他们将复制的意图.不过,如果在那里指定它们更方便,那可能会很有趣.但我发现真正有趣的是 F# 编译器完全忽略了 AttributeUsageAttribute,对于 [ProtoMember] 来说,它是:

If they did anything, they would be duplicating the intent of <ProtoInclude(n)>. If it is more convenient to specify them there, that might be interesting, though. But what I find really interesting about that is that the F# compiler completely ignores the AttributeUsageAttribute, which for [ProtoMember] is:

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field,
    AllowMultiple = false, Inherited = true)]
public class ProtoMemberAttribute {...}

是的,F# 编译器显然将其(非法)固定在方法上:

Yes the F# compiler clearly stuck that (illegally) on a method:

[ProtoMember(1)]
[CompilationMapping(SourceConstructFlags.UnionCase, 0)]
public static ProtoBufTests.Message NewMessageA(ProtoBufTests.MessageA item)

顽皮的 F# 编译器!

naughty F# compiler!