【问题标题】:Type.GetConstructor returns null on IphoneType.GetConstructor 在 Iphone 上返回 null
【发布时间】:2018-09-20 21:48:32
【问题描述】:

我正在为 Iphone 在 Xamarin 中开发一个应用程序,类似应用程序的 android 版本已准备好用于 Google Play。我在我的应用程序中使用 jabber-net 库来实现聊天功能。但是在设备上遇到了一些问题(Iphone 5 - IOS 7.0.3)。模拟器中不会出现这个问题,下面是方法代码。

public class QnameType
{
    /// <summary>
    /// Element name
    /// </summary>
    protected internal string Name;
    /// <summary>
    /// Element namespace URI
    /// </summary>
    protected internal string NS;
    /// <summary>
    /// Type to create for NS/Name pair
    /// </summary>
    protected internal Type  ElementType;

    /// <summary>
    /// Create a QnameType
    /// </summary>
    /// <param name="name"></param>
    /// <param name="ns"></param>
    /// <param name="typ"></param>
    public QnameType(string name, string ns, Type typ)
    {
        this.Name  = name;
        this.NS    = ns;
        this.ElementType = typ;
    }

    /// <summary>
    /// Is this the same qname by element name and namespace?
    /// </summary>
    /// <param name="obj"></param>
    /// <returns></returns>
    public override bool Equals(object obj)
    {
        if (obj == (object)this)
            return true;
        QnameType other = obj as QnameType;
        if (other == null)
            return false;
        return (other.Name == Name) && (other.NS == NS);
    }

    /// <summary>
    /// Get a hash over the name and namespace.
    /// </summary>
    /// <returns></returns>
    public override int GetHashCode()
    {
        return ToString().GetHashCode();
    }

    /// <summary>
    /// Namespace|Name
    /// </summary>
    /// <returns></returns>
    public override string ToString()
    {
        return NS + "|" + Name;
    }
}
public interface IPacketTypes
{
    /// <summary>
    /// QName to type mappings.
    /// </summary>
    QnameType[] Types { get; }
}
public class ElementFactory
{
    private Hashtable m_types = new Hashtable();
    private static readonly Type[] s_constructorTypes =
        new Type[] { typeof(string),
                       typeof(XmlQualifiedName),
                       typeof(XmlDocument) };
    public void AddType(IPacketTypes list)
    {
        foreach (QnameType qn in list.Types)
        {
        this.AddType(qn.Name, qn.NS, qn.ElementType);
        }
    }
    public void AddType(string localName, string ns, Type t)
    {
         Debug.Assert(t.IsSubclassOf(typeof(Element)));
         ConstructorInfo ci = t.GetConstructor(s_constructorTypes);
         Debug.Assert(ci != null);
         AddType(new XmlQualifiedName(localName, ns), ci);
    }
    public Element GetElement(string prefix, XmlQualifiedName qname, XmlDocument doc)
    {
        ConstructorInfo ci = (ConstructorInfo) m_types[qname];
        if (ci == null)
        {
            return new Element(prefix, qname, doc);
        }
        return (Element) ci.Invoke
            (new object[] {prefix, qname, doc});
    }

    /// <summary>
    /// Get a constructor for the appropriate type for the given qname.
    /// </summary>
    public ConstructorInfo this[XmlQualifiedName qname]
    {
        get { return (ConstructorInfo) m_types[qname]; }
    }
}

t.GetConstructor() 在 Iphone 上返回 null,但在模拟器上工作正常。

编辑:添加更多细节,

我们将不胜感激。

谢谢

【问题讨论】:

    标签: c# ios xamarin.ios xamarin.android xamarin


    【解决方案1】:

    这可能是正常的,取决于t 本身 - 它代表什么类型?

    默认情况下,托管链接器在模拟器版本中被禁用(不链接)。这意味着每种类型都将成为应用程序的一部分。

    但是,设备构建的默认设置是 Link SDK。这意味着从应用程序中删除未使用的类型(使用静态分析找到)。这允许减小应用程序的大小(通过不在每个应用程序内编译/传送整个 .NET BCL)。

    静态分析无法检测到代码的动态使用,例如反射。如果您的应用程序依赖于反射,则需要保留代码:使用[Preserve] 属性、XML 文件或添加一些额外的代码,这些代码将为链接器提供 hint 以保留所需的成员。

    更多详情请参阅documentation

    【讨论】:

    • 我已经将设备的链接器行为设置为“链接所有程序集”,但对于模拟器,它仍然是“不链接”抱歉我是菜鸟,我该如何添加 [Preserve] 属性?我必须在哪里给出这个命令“--xml=FILE”?您提供的链接说“如果您使用 XML 序列化,您可能希望保留类型的属性。”是的,我的应用程序处理 XML 序列化。在 android 应用程序中,我没有遇到像这样的任何问题。 ——
    • Android 链接器默认是不同的(取决于您如何部署应用程序)。 XML 序列化是一个(常见但不是唯一的)使用反射的示例(并且可能需要保留额外的代码)。请编辑您的问题(不是 cmets)以添加一些其他详细信息(例如 t 的类型是什么)。
    【解决方案2】:

    除了poupou的回答:

    如果您因为 Unity3D 遇到类似问题而对这个问题感到困惑,请查看此页面:https://docs.unity3d.com/Manual/IL2CPP-BytecodeStripping.html

    一般来说,该页面向您展示了如何确保所有内容都包含在 IL2CPP 构建中:

    • 在你的类上使用[Preserve]关键字

    • link.xml 文件添加到您的资产根目录中

    【讨论】:

      猜你喜欢
      • 2021-01-16
      • 2012-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 2016-01-26
      • 2021-11-21
      • 2015-06-11
      相关资源
      最近更新 更多