简体   繁体   English

在构建到 UWP 和 Il2CPP 后,通用方法中的 AOT(提前)出现问题

[英]Problem with AOT (ahead of time) in a generic method after built to UWP and Il2CPP

I have a generic method for trying to get a generic value from a dictionary via key using my own TryGetValue like (of course cropped a lot to the essential)我有一个通用方法,用于尝试使用我自己的TryGetValue之类的键通过键从字典中获取通用值(当然,对基本内容进行了很多裁剪)

public class BaseExample
{
    public virtual bool TryGetValue<T>(string key, out T value)
    {
        value = default;
        return false;
    }
}

public class Example : BaseExample
{
    private Dictionary<string, Item> _items = new Dictionary<string, Item>();

    public override bool TryGetValue<T>(string key, out T value)
    {
        value = default;
        if (!GetItem(key, value, out var setting)) { return false; }

        value = (T)setting.Value;
        return true;
    } 

    private bool GetItem<T>(string key, T value, out Item item)
    {
        item = null;

        if (!_items.ContainsKey(key))
        {
            item = null;
            return false;
        }

        item = _items[key];

        return true;
    }
}

This works in the Unity Editor but as soon as this is built to UWP and IL2CPP as soon as I try to run the method with eg这在 Unity 编辑器中有效,但是一旦我尝试使用 eg 运行该方法,它就会构建为 UWP 和 IL2CPP

var value = example.TryGetValue<int>("SomeKey");

It throws a它抛出一个

 System.ExecutionEngineException: Attempting to call method 'Example::TryGetValue<System.Int32>' for which no ahead of time (AOT) code was generated.

What could be the reason for this and how can I fix it?这可能是什么原因,我该如何解决?

For my specific case (if it helps anyone) I was using对于我的具体情况(如果它对任何人有帮助)我正在使用

WrapperMethod<WeatherFrameInfo[]>();

WrapperMethod<T>() {
    JsonConvert.DeserializeObject<T>(json);
}

Which lead to the error:导致错误:

2022/03/17 14:53:32.888 13468 13524 Error Unity ExecutionEngineException: Attempting to call method 'System.Collections.Generic.List`1[[WeatherFrameInfo, ScriptsAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]::.cctor' for which no ahead of time (AOT) code was generated.
2022/03/17 14:53:32.888 13468 13524 Error Unity   at System.Reflection.RuntimeConstructorInfo.InternalInvoke (System.Object obj, System.Object[] parameters, System.Boolean wrapExceptions) [0x00000] in <00000000000000000000000000000000>:0 
2022/03/17 14:53:32.888 13468 13524 Error Unity   at Newtonsoft.Json.Utilities.LateBoundReflectionDelegateFactory+<>c__DisplayClass5_0`1[T].<CreateDefaultConstructor>b__1 () [0x00000] in <00000000000000000000000000000000>:0 
2022/03/17 14:53:32.888 13468 13524 Error Unity   at Newtonsoft.Json.Serialization.JsonArrayContract.CreateTemporaryCollection () [0x00000] in <00000000000000000000000000000000>:0 
2022/03/17 14:53:32.888 13468 13524 Error Unity   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewList (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, System.Boolean& createdFromNonDefaultCreator) [0x00000] in <00000000000000000000000000000000>:0 
2022/03/17 14:53:32.888 13468 13524 Error Unity   at Newtons

I theorized that Newtonsoft is converting my array input to a List at some point so I refactored my code to do that ahead of time and violá我推测Newtonsoft会在某个时候将我的数组输入转换为List ,所以我重构了我的代码以提前完成此操作,violá

WrapperMethod<List<WeatherFrameInfo>>();

WrapperMethod<T>() {
    JsonConvert.DeserializeObject<T>(json);
}

Ok after some further research and tests the conclusion to why this happened is as follows:好的,经过一些进一步的研究和测试,为什么会发生这种情况的结论如下:

Since according method was part of an interface and only either called via interface or via the base class the Example.TryGetValue method was never explicitly called via this class.由于根据方法是接口的一部分,并且只能通过接口或通过基础 class 调用,因此从未通过此 class 显式调用Example.TryGetValue方法。

Since the Example class lives in a different Assembly than the interface and Base class the code for Example.TryGetValue was somehow stripped of on compile time (since the compiler thinks it is never used anyway) and therefore missing later in the build.由于Example class 与接口和基础 class 位于不同的程序集中,因此Example.TryGetValue的代码在编译时以某种方式被剥离(因为编译器认为它无论如何都不会使用),因此在构建的后期丢失。


I now know the reason and what to have in mind for the future but not yet a real solution except having an explicit implementation and calling that so it is not stripped of...我现在知道原因以及未来要考虑什么,但除了有一个明确的实现并调用它,它还不是一个真正的解决方案,所以它不会被剥夺......

To work around an AOT issue like this, you can force the compiler to generate the proper code.要解决此类 AOT 问题,您可以强制编译器生成正确的代码。 You can add the following example method in your class:您可以在 class 中添加以下示例方法:

public void UsedOnlyForAOTCodeGeneration() 
{
    // YOUR CODE HERE

    // Include an exception so we can be sure to know if this method is ever called.
    throw new InvalidOperationException("This method is used for AOT code generation only. 
    Do not call it at runtime.");
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM