Referencia
Múltiples ensamblados y renombrado entre ellos
Ofusca juntos los ensamblados interdependientes para que las referencias entre ensamblados sigan siendo válidas — incluido cómo renombrar los miembros públicos compartidos entre tus propios ensamblados.
Si tu producto distribuye más de un ensamblado y estos se referencian entre sí — una app más sus bibliotecas, o un conjunto de bibliotecas — ofúscalos juntos en una sola ejecución. Nebula mantiene así consistente cada referencia entre ensamblados.
Por qué ofuscarlos juntos
Cuando el ensamblado A llama a un tipo o miembro público en el ensamblado B, renombrar ese miembro en B
solo es seguro si la referencia en A se reescribe al nuevo nombre al mismo tiempo. Nebula solo puede
reescribir referencias en ensamblados que formen parte de la misma ejecución — así que lista todos los
ensamblados interdependientes en inputs:
{
"inputs": [
"bin/Release/MyApp.dll",
"bin/Release/MyApp.Core.dll",
"bin/Release/MyApp.Plugins.dll"
],
"outputDirectory": "bin/Release/obf"
}
Qué se renombra de forma predeterminada
- Los miembros internos / privados se renombran — no son visibles fuera del ensamblado, así que esto siempre es seguro.
- La API pública se preserva (
preservePublicApitiene el valor predeterminadotrue), de modo que el código fuera de la ejecución que referencia a tus ensamblados sigue funcionando. - Incluso con
preservePublicApi: false, Nebula autodetecta los miembros públicos que un input hermano referencia y mantiene esos nombres estables — a menos que habilites explícitamente el renombrado entre ensamblados (abajo). autoDetect(activado de forma predeterminada) también preserva los nombres usados mediante reflexión, serialización, DI y XAML, y respeta[Obfuscation].
Renombrar miembros públicos compartidos entre tus ensamblados
Este es el caso importante para los proyectos multiensamblado: quieres renombrar un método o tipo público en B que A llama. La configuración del proyecto necesita tres cosas:
{
"inputs": ["bin/Release/A.dll", "bin/Release/B.dll"], // EVERY caller must be listed here
"outputDirectory": "bin/Release/obf",
"preservePublicApi": false, // allow public members to be renamed
"crossAssemblyRename": true // rename shared public types AND rewrite the references in the siblings
}
Con esto en su lugar:
- Los miembros públicos de B se renombran.
- Las referencias de A a ellos se reescriben a los nuevos nombres, y A también se ofusca y se escribe.
- Despliegas A y B ofuscados juntos — el A original ya no resolvería los miembros renombrados.
La regla que hay que recordar
Cada ensamblado que llame a un miembro público que quieras renombrar debe estar en inputs. Si un llamador no
está en la ejecución, seguirá referenciando el nombre antiguo y se romperá en tiempo de carga/JIT. Por lo tanto:
- No puedes renombrar API pública de la que dependa código externo o de terceros (que no puedes incluir en la ejecución). Mantén
preservePublicApi: truepara esa superficie, o acótala coninclude/excludeabajo. - El valor predeterminado (
preservePublicApi: true) existe precisamente para proteger a esos llamadores externos — solo se renombran los internos.
Mantener estables puntos de entrada públicos específicos
Incluso al renombrar miembros públicos, algunos nombres deben sobrevivir — una interfaz de plugin, un punto de entrada público, tipos creados por reflexión o DI, contratos de serialización. Usa:
exclude— fuerza la preservación de nombres específicos. Un nombre completo de tipo preserva el tipo y todos sus miembros;"Namespace.Type.Method"preserva un único miembro:"exclude": ["MyApp.Plugins.IPlugin", "MyApp.Api.PublicFacade"]include— una lista de permitidos: cuando no está vacía, solo los tipos listados (y sus miembros) son elegibles para el renombrado y todo lo demás se preserva. Útil para renombrar solo tus bibliotecas internas dejando intacta una superficie de SDK pública.autoDetectya preserva automáticamente los objetivos de reflexión/serialización/[Obfuscation]— rara vez necesitas listarlos a mano.
Miembros virtuales, de interfaz, genéricos, campos, propiedades y eventos
Nebula preserva la consistencia de sobrescrituras / interfaces / genéricos entre ensamblados. Un método
sobrescrito, una implementación de interfaz, un tipo o método genérico, y los campos, propiedades,
eventos y sobrecargas públicos se renombran todos de forma consistente, y cada referencia entre ensamblados a ellos se
reescribe. Esto está cubierto por nuestra suite de pruebas, que ofusca dos ensamblados interdependientes
juntos (con crossAssemblyRename) y ejecuta la app que los referencia para confirmar que cada referencia —
incluidas todas esas formas — sigue resolviéndose.
Nombres seguros (strong-naming) en todo el conjunto
Si vuelves a firmar con tu propia clave (strongNameKeyFile), Nebula actualiza la referencia de ensamblado de cada hermano
para que lleve el nuevo token de clave pública, de modo que todo el conjunto se mantenga consistente y cargable.
Ejemplo resuelto
Dos ensamblados — SampleLibA.dll (una biblioteca) y SampleAppB.dll (una app que la llama):
{
"inputs": ["out/SampleLibA.dll", "out/SampleAppB.dll"],
"outputDirectory": "out/obf",
"preservePublicApi": false,
"crossAssemblyRename": true,
"controlFlowObfuscation": true,
"encryptStrings": true
}
nebula --config nebula.config.json
Ambos ensamblados salen ofuscados; las referencias de la app a los miembros de la biblioteca ahora renombrados se
reescriben; despliegas ambos desde out/obf.
Regla general: incluye cada ensamblado que controles que referencie la superficie renombrada; mantén
preservePublicApi: true(o usaexclude) para cualquier API de la que dependa código externo.