2017-02-15 3 views
1

Во-первых, общее замечание, что Xamarin называет своим «компоновщиком», на самом деле является скорее «удалением мертвого кода». Предполагается, что некачественный код может превратиться в компилируемое приложение.Xamarin linker удаляет все конструкторы, но сохраняет методы экземпляра?

У меня есть тип в моем приложении. Когда я использую отражение, чтобы получить его конструкторы, я вижу нулевые конструкторов:

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

Вы пытались задать описание пользовательских ссылок? 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"; 
    } 
    } 
} 

У меня также есть хотя бы один случай, когда код в классе, который удаляется компоновщиком, тем не менее заставляет другой класс не удаляться. Я предполагаю, что это ошибка; однако мой пример довольно востребован, и мои попытки получить простой реестр не удались.

0

Вы пытались использовать атрибут Preserve? Компоновщик не будет «оптимизировать» код декорированный с ним:

[Xamarin.iOS.Foundation.Preserve] 

Для получения дополнительной информации обратитесь к документации Xamarin here

+0

Моя проблема в обратном - код, который я хочу удалить, сохраняется. –

Смежные вопросы