Xamarin.iOS 链接器删除 class 中反射所需的成员

Xamarin.iOS Linker removes members in class needed for reflection

在 Xamarin 项目中,我将链接器行为设置为 "Link all references"。这样做时,程序集通过删除未使用的成员得到优化。一个问题是,它实际上并没有意识到我们需要它们进行反射。我知道我们可以使用 Preserve 属性来告诉链接器将所有符号保留在 class 中,但是如果程序集是 DLL 或者不是 iOS 项目(不引用monotuch 程序集,并且不能)。有没有一种方法可以将库中的所有 classes 设置为 "preserve",忽略它,或者只设置某些 classes 进行优化(反向 PreserveAttribute)?

您可以做的是创建一个名为 LinkerPleaseInclude.cs 的文件。您实际上可以根据需要命名它,但是这个名字很有意义。在那里你可以为你需要的类型创建虚拟对象,尤其是反射。这样 link 就会看到您 "need" 它并且不会删除它。这是一个 example of a LinkerPleaseInclude.cs 文件。如果您需要的 classes 在第 3 方 DLL 中定义,这将很有用。

更新:

啊,我误读了您的原文 post,以为您在谈论您无法控制的第 3 方 DLL。因此,如果您有一个非 xamarin.iOS 库,您仍然可以使用 Preserve 属性。但是,您必须在您的库项目中像这样定义它。:

public sealed class PreserveAttribute : System.Attribute 
{
    public bool AllMembers;
    public bool Conditional;
}

它与您定义 Preserve class 的命名空间无关,因为 linker 仅搜索 Preserve 名称。然后您可以像往常一样使用 Preserve 属性。所以如果你想保留 class 和所有 50 个属性,那么你可以这样做:

[Preserve(AllMembers=true)]
public MyClass
{
   //code here
}

@SharpMobileCode 给出了很好的解释,但是还有另外两种方法可以解决这个问题。

  1. 使用 XML 文件并在项目的选项中使用 --xml=your.file,在 Additional mtouch arguments 下。当您无法更改程序集的源代码 - 或者 - 当您 want/need 使用工具生成要保留的成员列表时,这可能很有用;

  2. 使用新的 Preserve(Type) 构造函数。这允许您在已经引用 Xamarin.iOS.dlldifferent 程序集(例如您的主 .exe)中添加保留指令(因此无需定义您自己的类型)。例如

[assembly: Preserve (typeof (MyType), AllMembers = true)]

对于任何使用反射来设置 UIKit 视图属性的人,这里是我的 "Bread and Butter" 保留配置。

只需在您的 Xamarin iOS 应用程序项目中创建一个新的 class 并将其命名为 "LinkerGuard.cs" 或 "PreserveConfiguration.cs"

把这个放进去:

using CoreAnimation;
using CoreGraphics;
using Foundation;
using UIKit;


[assembly: Preserve (typeof (UIResponder), AllMembers = true)]
[assembly: Preserve (typeof (UIControl), AllMembers = true)]
[assembly: Preserve (typeof (UIView), AllMembers = true)]
[assembly: Preserve (typeof (UIButton), AllMembers = true)]
[assembly: Preserve (typeof (UILabel), AllMembers = true)]
[assembly: Preserve (typeof (UIImageView), AllMembers = true)]
[assembly: Preserve (typeof (UITextField), AllMembers = true)]
[assembly: Preserve (typeof (UISwitch), AllMembers = true)]
[assembly: Preserve (typeof (UIActivityIndicatorView), AllMembers = true)]
[assembly: Preserve (typeof (UIDatePicker), AllMembers = true)]
[assembly: Preserve (typeof (UIScrollView), AllMembers = true)]
[assembly: Preserve (typeof (UIWebView), AllMembers = true)]
[assembly: Preserve (typeof (UIPageControl), AllMembers = true)]
[assembly: Preserve (typeof (UIToolbar), AllMembers = true)]
[assembly: Preserve (typeof (UIStepper), AllMembers = true)]
[assembly: Preserve (typeof (UISegmentedControl), AllMembers = true)]
[assembly: Preserve (typeof (UISearchBar), AllMembers = true)]

[assembly: Preserve (typeof (UIScreen), AllMembers = true)]
[assembly: Preserve (typeof (UIWindow), AllMembers = true)]

[assembly: Preserve (typeof (UIBarItem), AllMembers = true)]

[assembly: Preserve (typeof (UINavigationBar), AllMembers = true)]


[assembly: Preserve (typeof (UITabBar), AllMembers = true)]
[assembly: Preserve (typeof (UITabBarItem), AllMembers = true)]
[assembly: Preserve (typeof (UIBarButtonItem), AllMembers = true)]

[assembly: Preserve (typeof (UITextFieldCondition), AllMembers = true)]
[assembly: Preserve (typeof (UIViewContentMode), AllMembers = true)]
[assembly: Preserve (typeof (UITextAlignment), AllMembers = true)]
[assembly: Preserve (typeof (UIControlContentHorizontalAlignment), AllMembers = true)]

[assembly: Preserve (typeof (UIReturnKeyType), AllMembers = true)]
[assembly: Preserve (typeof (UIDataDetectorType), AllMembers = true)]
[assembly: Preserve (typeof (UIKeyboardType), AllMembers = true)]

[assembly: Preserve (typeof (UITextFieldChange), AllMembers = true)]

[assembly: Preserve (typeof (UITableView), AllMembers = true)]
[assembly: Preserve (typeof (UICollectionView), AllMembers = true)]
[assembly: Preserve (typeof (UITableViewCell), AllMembers = true)]
[assembly: Preserve (typeof (UICollectionViewCell), AllMembers = true)]

[assembly: Preserve (typeof (UITableViewDataSource), AllMembers = true)]
[assembly: Preserve (typeof (UICollectionViewDataSource), AllMembers = true)]

[assembly: Preserve (typeof (UIViewController), AllMembers = true)]
[assembly: Preserve (typeof (UITabBarController), AllMembers = true)]
[assembly: Preserve (typeof (UINavigationController), AllMembers = true)]

[assembly: Preserve (typeof (UIDocument), AllMembers = true)]


[assembly: Preserve (typeof (UITapGestureRecognizer), AllMembers = true)]
[assembly: Preserve (typeof (UIGestureRecognizer), AllMembers = true)]

[assembly: Preserve (typeof (CGColor), AllMembers = true)]
[assembly: Preserve (typeof (UIColor), AllMembers = true)]
[assembly: Preserve (typeof (UIFont), AllMembers = true)]
[assembly: Preserve (typeof (UIImage), AllMembers = true)]

[assembly: Preserve (typeof (NSObject), AllMembers = true)]
[assembly: Preserve (typeof (NSAttributedString), AllMembers = true)]
[assembly: Preserve (typeof (NSLayoutConstraint), AllMembers = true)]
[assembly: Preserve (typeof (CAKeyFrameAnimation), AllMembers = true)]
[assembly: Preserve (typeof (NSIndexPath), AllMembers = true)]