【问题标题】:MakeGenericMethod/MakeGenericType on Xamarin.iOSXamarin.iOS 上的 MakeGenericMethod/MakeGenericType
【发布时间】:2014-07-05 15:50:24
【问题描述】:

我试图弄清楚从 Xamarin 为 iOS 部署时限制的真正含义。

http://developer.xamarin.com/guides/ios/advanced_topics/limitations/

我的印象是您没有 JIT,因此任何 MakeGenericMethod 或 MakeGenericType 都无法工作,因为这需要 JIT 编译。

我还了解到,在模拟器上运行时,这些限制不适用,因为模拟器没有在完全 AOT(提前)模式下运行。

设置我的 Mac 以便我可以部署到我的手机后,我会在实际设备 (iPhone) 上运行时,除了以下测试失败。

    [Test]
    public void InvokeGenericMethod()
    {
        var method = typeof(SampleTests).GetMethod ("SomeGenericMethod");

        var closedMethod = method.MakeGenericMethod (GetTypeArgument());

        closedMethod.Invoke (null, new object[]{42});

    }

    public static void SomeGenericMethod<T>(T value)
    {
    }


    private Type GetTypeArgument()
    {
        return typeof(int);
    }

事情是成功完成,我真的不明白为什么。这段代码不需要JIT编译吗?

为了“让它崩溃”,我还用 MakeGenericType 做了一个测试。

    [Test]
    public void InvokeGenericType()
    {
        var type = typeof(SomeGenericClass<>).MakeGenericType (typeof(string));

        var instance = Activator.CreateInstance (type);

        var method = type.GetMethod ("Execute");

        method.Invoke (instance, new object[]{"Test"});

    }


public class SomeGenericClass<T>
{
    public void Execute(T value)
    {

    }
}

在没有 JIT 的情况下如何工作?

我错过了什么吗?

【问题讨论】:

  • 该代码可以进行 AOT 编译,因此可以毫无问题地工作。您将遇到限制的地方是生成 IL 代码。代码生成适用于 Android 和 Windows Phone,但不适用于 iOS。
  • 根据这篇文章,MakeGenericType 将导致 MSIL 被动态生成。 msdn.microsoft.com/en-us/magazine/cc163610.aspx如果真是这样,我不明白它是如何工作的。
  • 我实际上是错的,因为代码会因激进的链接选项而失败(除非代码中的其他地方有对 SomeGenericClass{string} 的引用)。请在下面使用一些示例代码查看我的答案。

标签: c# ios iphone xamarin.ios xamarin


【解决方案1】:

为了使代码失败,请转到 iOS 项目选项,选项卡“iOS 构建”并将“链接器行为:”更改为“链接所有程序集”。运行代码将导致异常,它将是类型为 XXX 的默认构造函数未找到。

现在,在您的代码中引用 SomeGenericClass{string},该方法将正常运行。添加的两行会导致编译器在二进制文件中包含 SomeGenericClass{string}。请注意,这些行可以在编译成二进制文件的应用程序中的任何位置,它们不必在同一个函数中。

    public void InvokeGenericType()
    {
        // comment out the two lines below to make the code fail
        var strClass = new SomeGenericClass<string>();
        strClass.Execute("Test");

        var type = typeof(SomeGenericClass<>).MakeGenericType (typeof(string));

        var instance = Activator.CreateInstance (type);

        var method = type.GetMethod ("Execute");

        method.Invoke (instance, new object[]{"Test"});
    }

【讨论】:

  • 那么你的意思是,只要链接器行为没有设置为“链接所有程序集”,MakeGenericType 和 MakeGenericMethod 就可以工作?
  • 是的,因为链接器将包含泛型类的所有可能组合。这可能会导致较大的二进制文件,因此通常建议发布版本使用积极链接。使用默认设置,如果“SomeGenericClass”被 SDK 库中的通用替换,我认为它会失败。
  • 如果我用 PreserveAttribute 标记类 SomeGenericClass 怎么办?它还会被链接吗?
猜你喜欢
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 2017-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-11
相关资源
最近更新 更多