【问题标题】:Preserve anonymous types when linking链接时保留匿名类型
【发布时间】:2014-07-10 19:47:25
【问题描述】:

我有一些代码使用匿名类型的反射将数据填充到 URI 模式中,如下所示:

var uri = UriUtility.FromPattern("/{action}/{id}.{contentType}", new {
    action = "foo",
    id = 1234,
    contentType = "xml"
});

当我使用 MonoTouch 选项“链接所有程序集”时,匿名类型成员被剥离,我的代码在运行时失败。有没有办法告诉 MonoTouch 链接器保留所有匿名类型的成员?

更新

这里有一个完整的测试用例来演示这个问题。仅链接 SDK 程序集时测试通过,链接所有程序集时失败。

using System;
using System.Collections.Generic;
using System.Reflection;
using MonoTouch.Foundation;
using NUnit.Framework;

namespace LinkerTests.iOS
{
    [Preserve(AllMembers = true)]
    [TestFixture]
    public class AnonymousTypeTests
    {
        [Test]
        public void Test()
        {
            var str = string.Join(",", AnonymousTypeUtil.GetProperties(new { a = "a", b = "b" }));
            Assert.AreEqual("a=a,b=b", str);
        }
    }

    internal static class AnonymousTypeUtil
    {
        public static IEnumerable<string> GetProperties(object o)
        {
            foreach (var property in o.GetType().GetRuntimeProperties())
            {
                object value = property.GetValue(o);
                yield return property.Name + "=" + value;
            }
        }
    }
}

【问题讨论】:

  • 听起来您的问题与匿名类型实际上是内部的而不是公共的这一事实有关,因此您将无法从其他程序集中引用该类型。我还想说明一个事实,我强烈建议您不要使用这种特殊的编码模式。您不应该将成员的姓名视为数据;改为使用成对的字符串。
  • 我不认为内部与公共有任何关系。链接器删除公共成员和类型以及内部。

标签: c# xamarin.ios xamarin


【解决方案1】:

我收到了 Xamarin 的确认,表明这目前是不可能的。

【讨论】:

    【解决方案2】:

    我不确定这是链接器问题,即三个字段已分配/使用并且不会被链接器删除)至少它不是匿名类型的问题。

    启用链接器(链接全部)后,这是我在 Xamarin Studio 中看到的内容(立即窗口):

    > ? o
    {{ action = foo, id = 1234, contentType = xml }}
    

    但是,就像@Servy 提到的那样,这些字段是公开的(这是编译器,而不是这样做的链接器)。您需要在反射代码中将它们作为非公共字段访问,例​​如

    > o.GetType ().GetField ("<action>", BindingFlags.Instance | BindingFlags.NonPublic)
    {System.String <action>}
        Attributes: System.Reflection.FieldAttributes.InitOnly|System.Reflection.FieldAttributes.Private
        DeclaringType: {<>__AnonType0`3[System.String,System.Int32,System.String]}
        FieldHandle: {System.RuntimeFieldHandle}
        FieldType: {System.String}
        IsInitOnly: true
        IsLiteral: false
        IsNotSerialized: false
        IsPrivate: true
        IsStatic: false
        MemberType: 4
        MetadataToken: 67108914
        Name: "<action>"
        ReflectedType: {<>__AnonType0`3[System.String,System.Int32,System.String]}
        Non-public members: 
    

    如果不知道UriUtility.FromPattern 使用反射做什么(以及如何),我无法进一步诊断。您可能想要更新您的问题和/或提交带有完整测试用例的bug report

    OTOH 我确信 this 示例应该与链接器和反射一起正常工作(但在启用链接器时使用反射仍然很棘手,因为静态分析无法精确确定正在使用的内容)。

    【讨论】:

    猜你喜欢
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多