首先,一般说明,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();
}
}
}
更新:摆脱所有演员都无法解决问题。我在许多地方称为超类对象的虚拟成员。那是我的下一个猜测,但是如果这是问题,修复会很混乱。
至少在我的情况下,在类型上调用任何静态方法都会导致保存大量实例成员。我从字面上尝试了:
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";
}
}
}
我还看到了至少一种情况,尽管链接器将删除的类中的代码导致另一个类不被删除。我认为这是一个错误;但是,我的示例相当涉及,我试图获得简单的repro的尝试失败了。
您是否尝试过使用Preserve属性?链接器不会"优化"用它装饰的代码:
[Xamarin.iOS.Foundation.Preserve]
有关更多信息,请参见此处的Xamarin文档