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

MessagePack.Generator - Issues with generic #1753

Open
RAORelewise opened this issue Jan 29, 2024 · 0 comments
Open

MessagePack.Generator - Issues with generic #1753

RAORelewise opened this issue Jan 29, 2024 · 0 comments

Comments

@RAORelewise
Copy link

RAORelewise commented Jan 29, 2024

I am currently trying to use the MessagePack.Generator tool to pre-create all formatters for our project. Our project uses a bunch of generics and i am wondering how to approach this, maybe i am doing something wrong.

So for the following code:

[Union(0, typeof(Dog))]
public abstract class Animal
{
}

[MessagePackObject]
public sealed class Dog : Animal
{
    
}

Everything works fine. But if i add generics:

[Union(0, typeof(Dog))]
public abstract class Animal<T>
{
}

[MessagePackObject]
public sealed class Dog : Animal<double>
{
    
}

I am getting this error:

PS C:\Projects\MessagePackGeneratorTest\MessagePackGeneratorTest> mpc -i .\MessagePackGeneratorTest.csproj -o MessagePackGenerated.cs
Project Compilation Start:MessagePackGeneratorTest
Project Compilation Complete:00:00:00.4858938
Method Collect Start
Fail in application running on MessagepackCompiler.RunAsync
MessagePackCompiler.CodeAnalysis.MessagePackGeneratorResolveFailedException: Serialization Object must mark MessagePackObjectAttribute. type: global::MessagePackGeneratorTest.Animal<T>
   at MessagePackCompiler.CodeAnalysis.TypeCollector.GetObjectInfo(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 609
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectObject(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 600
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectGeneric(INamedTypeSymbol type) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 550
   at MessagePackCompiler.CodeAnalysis.TypeCollector.CollectCore(ITypeSymbol typeSymbol) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 364
   at MessagePackCompiler.CodeAnalysis.TypeCollector.Collect() in D:\a\1\s\src\MessagePack.GeneratorCore\CodeAnalysis\TypeCollector.cs:line 305
   at MessagePackCompiler.CodeGenerator.GenerateFileAsync(Compilation compilation, String output, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.GeneratorCore\CodeGenerator.cs:line 67
   at MessagePack.Generator.MessagepackCompiler.RunAsync(String input, String output, String conditionalSymbol, String resolverName, String namespace, Boolean useMapMode, String multipleIfDirectiveOutputSymbols, String[] externalIgnoreTypeNames) in D:\a\1\s\src\MessagePack.Generator\MessagepackCompiler.cs:line 
66
   at ConsoleAppFramework.WithFilterInvoker.RunCore(ConsoleAppContext _)
   at ConsoleAppFramework.WithFilterInvoker.InvokeAsync()
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(Type type, MethodInfo methodInfo, Object instance, String[] args, Int32 argsOffset)
   at ConsoleAppFramework.ConsoleAppEngine.RunCore(Type type, MethodInfo methodInfo, Object instance, String[] args, Int32 argsOffset)

Why is it now required to add a MessagePackObject attribute? And even if i do add it. The next error is now that i do not have any public ctor, why is this now required?

[Union(0, typeof(Dog))]
[MessagePackObject]
public abstract class Animal<T>
{
}
MessagePackCompiler.CodeAnalysis.MessagePackGeneratorResolveFailedException: can't find public constructor. type:global::MessagePackGeneratorTest.Animal<T>

Alright.. so now i add the public ctor (side question, why doesnt it work using protected parameterless ctors in abstract classes either?):

[Union(0, typeof(Dog))]
[MessagePackObject]
public abstract class Animal<T>
{
    public Animal()
    {
        
    }
}

[MessagePackObject]
public sealed class Dog : Animal<double>
{
    public Dog()
    {
        
    }
}

Doing this the generator succeeded. BUT. It wont compile.

It is generating this formatter:

    public sealed class AnimalFormatter<T> : global::MessagePack.Formatters.IMessagePackFormatter<global::MessagePackGeneratorTest.Animal<T>>
    {

        public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::MessagePackGeneratorTest.Animal<T> value, global::MessagePack.MessagePackSerializerOptions options)
        {
            if (value == null)
            {
                writer.WriteNil();
                return;
            }

            writer.WriteArrayHeader(0);
        }

        public global::MessagePackGeneratorTest.Animal<T> Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options)
        {
            if (reader.TryReadNil())
            {
                return null;
            }

            reader.Skip();
            return new global::MessagePackGeneratorTest.Animal<T>();
        }
    }

Where it fails as you cant create an instance of an abstract type -> return new global::MessagePackGeneratorTest.Animal();

Why is it creating a formatter for this base type now? It looks completely different without the generics.

  • Version used: 2.5.140
  • Runtime: .net 7 class library
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

2 participants