Preventing Xamarin(/Mono?) from optimizing on iOS

2019-09-06 16:55发布

问题:

When I use reflection in ViewDidLoad like this:

foreach (var m in this.GetType().GetMethods()) {
            Console.WriteLine (m.Name); 
}

without any other code, methods like

Add
set_View

are not there; when I add;

public void PreventOptimizing() {
    var x = this.View; 
    this.View = x; 
    this.Add (null); 
}

to the class and without calling that method, they are there. So I assume the AOT compilation optimizes these methods away as they are not called. I don't know which methods it adds away so I would like the compiler, for my experiment, not to optimize anything away. How can that be done? Or is there another trick preventing automated removal of method?

Edit: so full code, if this isn't clear enough;

  1. result output will not contain 'Add' and 'set_View';
public class TestController : UIViewController
{

    public override void ViewDidLoad ()
  {
         base.ViewDidLoad ();

      foreach (var m in this.GetType().GetMethods()) {
          Console.WriteLine (m.Name); 
      }
    }
}
  1. Output does contain Add and set_View;
public class TestController : UIViewController
{
  public void PreventOptimizing() {
      var x = this.View; 
      this.View = x; 
      this.Add (null); 
  }
  public override void ViewDidLoad ()
  {
         base.ViewDidLoad ();

      foreach (var m in this.GetType().GetMethods()) {
          Console.WriteLine (m.Name); 
      }
    }
}

回答1:

You either set the linker option to "Link SDK assemblies only" or use the PreserveAttribute on the class.

Details are in Xamarin website: http://developer.xamarin.com/Guides/ios/Advanced_Topics/Linker/

Linker Behavior

The linking process can be customized in different ways. The primary mechanism for controlling the linker in Xamarin Studio is the Linker Behavior drop-down in the iOS Build Xamarin Studio's Project Options dialog box. In Visual Studio, this is located in project Properties, under iOS Build.

Preserving Code

When you use the linker it can sometimes remove code that you might have called dynamically either using System.Reflection.MemberInfo.Invoke, or by exporting your methods to Objective-C using the [Export] attribute and then invoking the selector manually.

In those cases, you can instruct the linker to consider either entire classes to be used or individual members to be preserved by applying the [Xamarin.iOS.Foundation.Preserve] attribute either at the class-level or the member-level. Every member that is not statically linked by the application is subject to be removed. This attribute is hence used to mark members that are not statically referenced, but that are still needed by your application.

For instance, if you instantiate types dynamically, you may want to preserve the default constructor of your types. If you use XML serialization, you may want to preserve the properties of your types.

You can apply this attribute on every member of a type, or on the type itself. If you want to preserve the whole type, you can use the syntax [Preserve (AllMembers = true)] on the type.

Sometimes you want to preserve certain members, but only if the containing type was preserved. In those cases, use [Preserve (Conditional=true)]



标签: ios mono xamarin