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

Problem with reflection for methods with many enums #323

Open
GoNextGroup opened this issue Feb 7, 2024 · 7 comments
Open

Problem with reflection for methods with many enums #323

GoNextGroup opened this issue Feb 7, 2024 · 7 comments

Comments

@GoNextGroup
Copy link

GoNextGroup commented Feb 7, 2024

Hello, Marc.

I try to use reflection in my project, but got problem with enums.

I have service with request record:


    [ProtoContract]
    public record GenerateTokenRequest
    {
        [ProtoMember(1)]
        public Guid UserId { get; init; }
        [ProtoMember(2)]
        public Roles Role { get; init; }
        [ProtoMember(3)]
        public ClientTypes ClientType { get; init; }
        [ProtoMember(4)]
        public TokenType TokenType { get; init; }
    }

The proto file was generated:

syntax = "proto3";
package SharedInterfaces.TokenService.SecurityInterfaces.Token;
import "protobuf-net/bcl.proto"; // schema for protobuf-net's handling of core .NET types

enum ClientTypes {
   ZERO = 0; // proto3 requires a zero value as the first item (it can be named anything)
   Dealer = 1;
   Executor = 2;
}
message GenerateTokenRequest {
   .bcl.Guid UserId = 1; // default value could not be applied: 00000000-0000-0000-0000-000000000000
   Roles Role = 2;
   ClientTypes ClientType = 3;
   TokenType TokenType = 4;
}
enum Roles {
   User = 0;
   Worker = 1;
   Setter = 2;
   Customer = 3;
   ManagerOP = 4;
   Manager = 5;
   Employee = 998;
   LegalEntity = 999;
}
enum TokenType {
   ZERO = 0; // proto3 requires a zero value as the first item (it can be named anything)
   Temporary = 1;
   Persistent = 2;
}
message UserToken {
   string AuthenticationType = 1;
   string Token = 2;
   .bcl.DateTime Expiration = 3;
   int64 ExpirationUnixTime = 4;
   ClientTypes ClientType = 5;
   Roles Role = 6;
}
service TokenGeneration {
   rpc Generate (GenerateTokenRequest) returns (UserToken);
}

So, when I try to use command docker run fullstorydev/grpcurl -plaintext -use-reflection 172.23.17.107:50029 describe SharedInterfaces.TokenService.SecurityInterfaces.Token.TokenGeneration

I got a message
Failed to resolve symbol "SharedInterfaces.TokenService.SecurityInterfaces.Token.TokenGeneration": proto: descriptor "SharedInterfaces.TokenService.SecurityInterfaces.Token.ZERO" already declared

I've tried to find solution in the internet/SO/tg chats, but without any success. Could you help me to fix this problem? Or is there no way just only change enum elements order starting not from 1, but from 0?

@mgravell
Copy link
Member

mgravell commented Feb 7, 2024

I think this comes down to name collisions; we should add a mode that optionally includes the enum name as a prefix in all enum names (including zero), so we generate TokenType_Zero, TokenType_Temporary, etc

unrelated: you might want to look at https://protobuf-net.github.io/protobuf-net/compatibilitylevel re the data and guid

@GoNextGroup
Copy link
Author

Thank you for your answer. Currently, I'll try to change ordering of elements starting from 0. Is it possible in future releases to change enum members generation style? Because the same collision can be in cases when 2 enums contain elements with same names.

@mgravell
Copy link
Member

mgravell commented Feb 7, 2024

Is it possible in future releases to change enum members generation style? Because the same collision can be in cases when 2 enums contain elements with same names.

Yes, that is what I was proposing - sorry if that was unclear.

@mgravell mgravell reopened this Feb 7, 2024
@GoNextGroup
Copy link
Author

Thank you! I'll wait for new release)))

@menaheme
Copy link

menaheme commented Feb 7, 2024

Why is this closed?

@GoNextGroup GoNextGroup reopened this Feb 7, 2024
@GoNextGroup
Copy link
Author

Why is this closed?

Sorry, my bad.

@erichiller
Copy link

I encountered this issue as well. To work around it globally for now I am using:

// model can be any or the default ProtoBuf.Meta.RuntimeTypeModel.Default;
model.AfterApplyDefaultBehaviour += ( obj, evt ) => {
    if ( evt.Type.IsEnum
      && evt.MetaType.GetEnumValues().None( static v => v.Value is 0 )
      && evt.MetaType.GetEnumValues().FirstOrDefault().Value switch {
             long  => false,
             ulong => false,
             uint  => false,
             _     => true
         } ) {
        evt.MetaType.SetEnumValues( [ new EnumMember( ( byte )0, $"{evt.MetaType.GetSchemaTypeName()}__ZERO__DOES_NOT_EXIST" ), ..evt.MetaType.GetEnumValues() ] );
    }
};

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

No branches or pull requests

4 participants