2017-02-15 15 views
1

まず、Xamarinが「リンカ」と呼ぶものは、実際には「デッドコードリムーバ」です。それはuncallableコードがコンパイルされたアプリケーションにそれを作るのを防ぐために仮定されます。Xamarinリンカはすべてのコンストラクタを削除しますが、インスタンスメソッドは保持しますか?

私のアプリにはタイプがあります。私はそのコンストラクタを取得するためにリフレクションを使用すると、私はゼロのコンストラクタを参照してください。私はそのインスタンスメンバを参照するためにリフレクションを使用する場合

private static int GetConstructorCount(Type type) { 
    ConstructorInfo[] constructors = type.GetConstructors(); 
    return constructors.Count(); 
} 

はまだ、私は多くの参照:上記から

private static void LogMemberInfo(Type type) { 
    int constructorCount = GetConstructorCount(type); 
    MyLoggingMethod(constructorCount, "Constructors"); 
    MemberInfo[] members = type.GetMembers(); 
    List<string> willLog = new List<string>(); 
    foreach(MemberInfo member in members) { 
    if (member.DeclaringType == type) { 
     willLog.Add(member.Name); 
    } 
    } 
    willLog.Sort(); 
    foreach (string str in willLog) { 
    MyLoggingMethod.LogLine(str); 
    } 
} 

出力は次のようになります。

0 Constructors 
lots of surviving members, including instance members 

これは問題です。タイプが他の多くのタイプのゲートウェイであるためです。私は、すべてのコンストラクタを取り除くことによって、すべてのインスタンスメンバーが消えてくれることを期待していました。彼らはしません。

これはリンカーのバグですか?それとも、まだインスタンスメンバーを取りたくない理由がありますか?

キャストを介してタイプのメンバーにアクセスします。多分これは問題ですか?

public class MySuperclass { 
    public static MySuperclass Instance {get; set;} 
} 

public MyClass: MySuperclass { 
    public static SomeMethod() { 
    MySuperclass object = MySuperclass.Instance; 
    MyClass castObject = object as MyClass; // castObject will always be null, as no constructors survived the linking process. But maybe the linker doesn't realize that? 
    if (castObject!=null) { 
     castObject.InstanceMethod(); 
    } 
    } 
} 

更新:すべてのキャストを取り除いても問題は解決しませんでした。私は多くの場所でスーパークラスオブジェクトの仮想メンバを呼び出しています。それは私の次の推測ですが、それが問題ならば、修正は面倒です。

+0

は、カスタムリンクの説明を指定しようとしたことがありXamarinのドキュメント? https://developer.xamarin.com/guides/cross-platform/advanced/custom_linking/ –

+0

いいえ、私はそこに行かなければならないかもしれませんが、まず何が起こっているのか理解したいと思います。 –

+0

リンカは非常にシンプルで(強力な)設計であり、私はJsonのシリアライゼーション、クロスアセンブリのクラス/メンバの削除などを処理するカスタムステップを書いています...コードを見たり、テストケースで実行したりすると、次のようなことができます。https://github.com/mono/linker/tree/master/linker – SushiHangover

答えて

0

少なくとも私の場合、あるタイプの静的メソッドを呼び出すと、多くのインスタンスメンバーが保持されます。私は、文字通り、この試みた:タイプは、リンカによって除去なった後は

public class MyType() { 
    public static bool DummyBool() { 
    return true; 
    } 
    // instance members here 
} 

を、私は)MyType.DummyBool(への呼び出しに入れます。これにより多くのインスタンスメンバが保持されました。

これは、すべての人に当てはまるわけではありません。しかし、それは私の場合でした。

彼らが呼び出されない場合であっても、静的クラスは、起動時に初期化されているすべての特性を有し、かつ全体としてクラスが保存されている場合、それらの性質が保存されているということであるに注意する別の狡猾なもの:

public static class StaticClass { 
    public static Foo FooProperty {get;} = new Foo(); // if any code that is not removed calls StaticClass.SomeString, then Foo will be preserved. 
    public static string SomeString { 
    get { 
     return "Hello"; 
    } 
    } 
} 

リンカによって削除されたクラスのコードが削除されない別のクラスを引き起こす少なくとも1つのケースも見ています。私はこれがバグだと思う。しかし、私の例はむしろ関与しており、簡単な再現を得る私の試みは失敗しました。

0

Preserve属性を使用してみましたか?リンカはそれで飾らコード「最適化」しません。詳細については

[Xamarin.iOS.Foundation.Preserve] 

を参照してくださいhere

+0

私の問題は反対です。削除したいコードが残っています。 –

関連する問題