繁体   English   中英

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

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

我有一个通用方法,用于尝试使用我自己的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;
    }
}

这在 Unity 编辑器中有效,但是一旦我尝试使用 eg 运行该方法,它就会构建为 UWP 和 IL2CPP

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

它抛出一个

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

这可能是什么原因,我该如何解决?

对于我的具体情况(如果它对任何人有帮助)我正在使用

WrapperMethod<WeatherFrameInfo[]>();

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

导致错误:

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

我推测Newtonsoft会在某个时候将我的数组输入转换为List ,所以我重构了我的代码以提前完成此操作,violá

WrapperMethod<List<WeatherFrameInfo>>();

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

好的,经过一些进一步的研究和测试,为什么会发生这种情况的结论如下:

由于根据方法是接口的一部分,并且只能通过接口或通过基础 class 调用,因此从未通过此 class 显式调用Example.TryGetValue方法。

由于Example class 与接口和基础 class 位于不同的程序集中,因此Example.TryGetValue的代码在编译时以某种方式被剥离(因为编译器认为它无论如何都不会使用),因此在构建的后期丢失。


我现在知道原因以及未来要考虑什么,但除了有一个明确的实现并调用它,它还不是一个真正的解决方案,所以它不会被剥夺......

要解决此类 AOT 问题,您可以强制编译器生成正确的代码。 您可以在 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