Compartir a través de


Vinculación de una aplicación .NET MAUI para Android

Cuando compilas la aplicación, .NET Multi-platform App UI (.NET MAUI) puede usar un enlazador llamado ILLink para reducir el tamaño general de la aplicación. ILLink reduce el tamaño mediante el análisis del código intermedio generado por el compilador. Elimina los métodos, propiedades, campos, eventos, estructuras y clases que no se usan para crear una aplicación que solo contenga el código y las dependencias de ensamblaje necesarios para ejecutarla.

Comportamiento del enlazador

El enlazador te permite recortar las aplicaciones de .NET MAUI Android. Cuando se habilita el recorte, el enlazador deja intactos los ensamblados y reduce el tamaño de los ensamblados del SDK quitando tipos y miembros que la aplicación no usa.

El comportamiento del enlazador se puede configurar para cada configuración de compilación de la aplicación. De forma predeterminada, el recorte está deshabilitado para las compilaciones de depuración y habilitadas para las compilaciones de versión.

Advertencia

Habilitar el enlazador para la configuración de depuración de la aplicación puede dificultar la experiencia de depuración, ya que puede quitar descriptores de acceso de propiedad que te permiten inspeccionar el estado de los objetos.

  1. En el Explorador de soluciones, haz clic con el botón derecho en el proyecto y selecciona Propiedades. A continuación, navega a la pestaña Opciones > de Android y asegúrate de que el recorte está habilitado para la configuración de compilación de versión:

    Captura de pantalla del comportamiento del enlazador para Android en Visual Studio.

Conservar código

Cuando se usa el enlazador, en ocasiones, se eliminará código al que puedes haber llamado de forma dinámica, incluso indirectamente. Puedes indicar al enlazador que conserve los miembros anotándolos con el atributo DynamicDependency. Este atributo se puede usar para expresar una dependencia en un tipo y subconjunto de miembros, o en miembros específicos.

Importante

Todos los miembros del BCL que no se pueden determinar estáticamente para usar por la aplicación están sujetos a su eliminación.

El atributo DynamicDependency se puede aplicar a constructores, campos y métodos:

[DynamicDependency("Helper", "MyType", "MyAssembly")]
static void RunHelper()
{
    var helper = Assembly.Load("MyAssembly").GetType("MyType").GetMethod("Helper");
    helper.Invoke(null, null);
}

En este ejemplo, DynamicDependency garantiza que el método Helper se mantenga. Sin el atributo, la vinculación eliminaría Helper de MyAssembly o eliminaría MyAssembly completamente si no se hace referencia a él en otro lugar.

El atributo especifica los miembros que se mantienen mediante string o mediante el atributo DynamicallyAccessedMembers. El tipo y el ensamblado están implícitos en el contexto del atributo o se especifican explícitamente en el atributo (mediante Type, o mediante objetos string para el tipo y el nombre del ensamblado).

Las cadenas de tipo y miembro usan una variación del formato de cadena de identificador de comentario de documentación de C#, sin el prefijo de miembro. La cadena de miembro no debe incluir el nombre del tipo declarante y puede omitir parámetros para mantener todos los miembros del nombre especificado. En los ejemplos siguientes se muestran usos válidos:

[DynamicDependency("Method()")]
[DynamicDependency("Method(System,Boolean,System.String)")]
[DynamicDependency("MethodOnDifferentType()", typeof(ContainingType))]
[DynamicDependency("MemberName")]
[DynamicDependency("MemberOnUnreferencedAssembly", "ContainingType", "UnreferencedAssembly")]
[DynamicDependency("MemberName", "Namespace.ContainingType.NestedType", "Assembly")]
// generics
[DynamicDependency("GenericMethodName``1")]
[DynamicDependency("GenericMethod``2(``0,``1)")]
[DynamicDependency("MethodWithGenericParameterTypes(System.Collections.Generic.List{System.String})")]
[DynamicDependency("MethodOnGenericType(`0)", "GenericType`1", "UnreferencedAssembly")]
[DynamicDependency("MethodOnGenericType(`0)", typeof(GenericType<>))]

Conservar ensamblados

Es posible especificar ensamblados que se deben excluir del proceso de vinculación, al mismo tiempo que se permite que otros ensamblados se vinculen de la forma habitual. Este enfoque puede ser útil cuando no se puede usar fácilmente el atributo DynamicDependency o no controlar el código que se está vinculando.

Cuando vinculas todos los ensamblados, puedes indicar al enlazador que omita un ensamblado estableciendo la propiedad de MSBuild TrimmerRootAssembly en una etiqueta <ItemGroup> del archivo de proyecto:

<ItemGroup>
  <TrimmerRootAssembly Include="MyAssembly" />
</ItemGroup>

Nota:

La extensión .dll no es necesaria al establecer la propiedad de MSBuild TrimmerRootAssembly.

Si el enlazador omite un ensamblado, se considera enraizado, lo que significa que se conservarán tanto este como todas sus dependencias estáticas. Puedes omitir ensamblados adicionales agregando más propiedades de MSBuild TrimmerRootAssembly a <ItemGroup>.

Conservar ensamblados, tipos y miembros

Puedes pasar al enlazador un archivo de descripción XML que especifica qué ensamblados, tipos y miembros deben conservarse.

Para excluir un miembro del proceso de vinculación al vincular todos los ensamblados, establece la propiedad de MSBuild TrimmerRootDescriptor en una etiqueta <ItemGroup> del archivo de proyecto en el archivo XML que define los miembros que se van a excluir:

<ItemGroup>
  <TrimmerRootDescriptor Include="MyRoots.xml" />
</ItemGroup>

Después, el archivo XML usa el formato de descriptor del optimizador para definir qué miembros excluir de la vinculación:

<linker>
  <assembly fullname="MyAssembly">
    <type fullname="MyAssembly.MyClass">
      <method name="DynamicallyAccessedMethod" />
    </type>
  </assembly>
</linker>

En este ejemplo, el archivo XML especifica un método al que accede dinámicamente la aplicación, que se excluye de la vinculación.

Cuando un ensamblado, tipo o miembro aparece en el XML, la acción predeterminada es conservación, lo que significa que, independientemente de si el enlazador cree que se usa o no, se conserva en la salida.

Nota:

Las etiquetas de conservación son ambiguamente inclusivas. Si no proporcionas el siguiente nivel de detalle, incluirá todos los elementos secundarios. Si se muestra un ensamblado sin ningún tipo, se conservarán todos los tipos y miembros del ensamblado.

Marcar un ensamblado como seguro para el enlazador

Si tienes una biblioteca en el proyecto o eres desarrollador de una biblioteca reutilizable y quieres que el enlazador trate el ensamblado como enlazable, puedes marcar el ensamblado como enlazador seguro agregando la propiedad de MSBuild IsTrimmable al archivo de proyecto para el ensamblado:

<PropertyGroup>
    <IsTrimmable>true</IsTrimmable>
</PropertyGroup>

Esto marca el ensamblado como "recortable" y habilita las advertencias de recorte para ese proyecto. Ser "recortable" significa que el ensamblado se considera compatible con el recorte y no debe tener advertencias de recorte al compilar el ensamblado. Cuando se usa en una aplicación recortada, el ensamblado tiene sus miembros sin usar recortados en la salida final.

Al establecer la propiedad de MSBuild IsTrimmable en true en tu archivo del proyecto, se inserta el atributo AssemblyMetadata en el ensamblado:

[assembly: AssemblyMetadata("IsTrimmable", "True")]

Como alternativa, puedes agregar el atributo AssemblyMetadata al ensamblado sin haber agregado la propiedad de MSBuild IsTrimmable al archivo del proyecto de tu ensamblado.

Nota:

Si la propiedad de MSBuild IsTrimmable está establecida para un ensamblado, esto invalida el atributo AssemblyMetadata("IsTrimmable", "True"). Esto te permite optar por recortar un ensamblado aunque no tenga el atributo o deshabilitar el recorte de un ensamblado que lo tenga.

Supresión de advertencias de análisis de código

Cuando el enlazador está habilitado, elimina IL que no es accesible estáticamente. Las aplicaciones que usan reflexión u otros patrones que crean dependencias dinámicas pueden romperse como consecuencia de ello. Para advertir sobre estos patrones, al marcar un ensamblado como seguro para el enlazador, los autores de bibliotecas deben establecer la propiedad de MSBuild SuppressTrimAnalysisWarnings en false:

<PropertyGroup>
  <SuppressTrimAnalysisWarnings>false</SuppressTrimAnalysisWarnings>
</PropertyGroup>

Si no se suprimen las advertencias de análisis de recorte, se incluirán advertencias sobre toda la aplicación, incluido el código propio, el de la biblioteca y el del SDK.

Representación de advertencias detalladas

El análisis de recorte genera como máximo una advertencia para cada ensamblado que procede de un elemento PackageReference, lo que indica que los aspectos internos del ensamblado no son compatibles con el recorte. Como autor de la biblioteca, al marcar un ensamblado como seguro para el enlazador, debes habilitar advertencias individuales para todos los ensamblados estableciendo la propiedad de MSBuild TrimmerSingleWarn en false:

<PropertyGroup>
  <TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>

Se muestran todas las advertencias detalladas, en lugar de reducirlas a una única advertencia por ensamblado.

Consulta también