1

My code:

public static IConfigurationBuilder AddModel<T> (
    this IConfigurationBuilder builder,
    T model,
    JsonSerializerOptions options = null)
{
    var dic = new Dictionary<string, T>
    {
        {typeof(T).Name, model}
    };

    byte[] bytes;
    if (options != null)
        bytes = JsonSerializer.SerializeToUtf8Bytes(dic, options);
    else
        bytes = JsonSerializer.SerializeToUtf8Bytes(dic);

    var mem = new MemoryStream(bytes);
    return builder.AddJsonStream(mem);
}

But il2cpp reports:

System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter`3[
[System.Collections.Generic.Dictionary`2[
[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[Microsoft.Extensions.Logging.LogLevel, Microsoft.Extensions.Logging.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],
[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[Microsoft.Extensions.Logging.LogLevel, Microsoft.Extensions.Logging.Abstractions, Version=5.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60]]::.ctor'
for which no ahead of time (AOT) code was generated.

However,DictionaryOfTKeyTValueConverter is internal. I can't create instance in Assembly-CSharp to avoid this error.

2
  • To me this looks related to code stripping! Since you have an interface you probably never really reference that type of yours directly so it gets stripped of during the build, you could try and enforce the code stripping to be skipped for that type Commented Jan 17, 2022 at 3:56
  • I can't access the internal type DictionaryOfTKeyTValueConverter,it was used by JsonSerializer.SerializeToUtf8Bytes Commented Jan 18, 2022 at 12:33

2 Answers 2

1

I am sure this problem has no perfect solution under Unity3d2020.3.22f. This is the most valuable report I've found: https://forum.unity.com/threads/il2cpp-does-not-generate-constructor-for-generic-classes-that-have-struct-as-parameter.997274 /. The root of the problem is that Il2cpp cannot generate internal type code with a value type generic parameter, and Microsoft.Extensions.Logging.LogLevel is a value type. The response plan is as follows:

  1. Not using value types as generic parameters
  2. Recompile System.Text.Json and expose its internal type
  3. Use a non-standard compiler

I use scheme 1 and expect Unity to optimize il2cpp's support for value types as soon as possible

Sign up to request clarification or add additional context in comments.

Comments

0

Elsewhere in your code, you need to specifically call AddMove with all the types you will ever need. That's because the compiler will need to build versions of the method for every type. In an AOT (Ahead of Time) environment, the code can't make new types at runtime.

For example, you might do something like:

void SetupAOT()
{
  _ = AddModel<ModelType> (default, new ModelType() );
  throw new InvalidOperationException("This method is only for AOT code generation.");
}

This way, it looks like you'll call the method, the compiler is made aware of Dictionary <string, ModelType> and the compiler then adds the correct code to work with AOT.

This method should also be referenced from a point in the code that won't ever be true. Compilers can determine methods that aren't ever called, and strip them. So, to make sure that method isn't stripped, you could do something like:

// Never modify this from the default false
private bool alwaysFalse {get;set;}

// ... elsewhere    
if ( alwaysFalse ) SetupAOT();

Alternatively, you could decorate to SetupAOT method with the Unity Preserve Attribute like this:

[Preserve]
void SetupAOT()
{
  // ...
}

You can read up on the PreserveAttribute here. My preference would be to try the [Preserve] approach first.

Here's the source code for the DictionaryOfTKeyTValueConverter in your original question.

3 Comments

The problem is the type System.Text.Json.Serialization.Converters.DictionaryOfTKeyTValueConverter I can't access.It used by JsonSerializer.SerializeToUtf8Bytes.The problem is not about Dictionary or T.
And my response is that you don't need to access DictionaryOfTKeyTValueConverter . If you take a look at your error, you'll notice the key point "for which no ahead of time (AOT) code was generated". You need to supply the code required to read your generic Dictionary before you compile it. When you have code for a concrete type, that code is generated by the compiler AOT. I've edited the answer to include a link to the source code you're asking for.
No……JsonSerializer.SerializeToUtf8Bytes try to creat DictionaryOfTKeyTValueConverter`2 instance which was not generated.I need to access DictionaryOfTKeyTValueConverter ,then il2cpp can generate the code.Unfortunately I can't access DictionaryOfTKeyTValueConverter .And link.xml looks useless in this case.The problem is not about any type,is about how to make il2cpp to generate the code of the internal type I need

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.