Plataforma 1C:Enterprise >> ¿Qué hay de nuevo? >> Aspectos Destacados de Funcionalidad

Esta característica está implementada en la versión 8.3.9.1818 de 1C:Enterprise.

En resumen, ahora puedes usar extensiones para modificar los módulos de las configuraciones estándar y agregar nuevos módulos.

O más bien, ahora puedes cambiar cualquier módulo, con la excepción de los módulos de formulario ordinarios:

Ten en cuenta que ya podías modificar los módulos de formulario gestionados en el pasado, pero ahora hemos introducido algunos cambios en este proceso.

Por simplicidad, nos referiremos a la frase “procedimiento/función” como “método”. Así, todos los cambios que puedes implementar en los módulos se pueden dividir en 4 grupos:

Cuando adoptas y extiendes un módulo de configuración estándar, tu módulo que lo extiende se encuentra en el mismo espacio de nombres que el módulo de configuración estándar. Por lo tanto, puedes acceder directamente a cualquier variable y método del módulo estándar cuando estás en el módulo que extiende una configuración estándar.

Si estás en otro módulo que existe en la extensión, tienes acceso a tus variables exportadas y métodos del módulo que extiende una configuración estándar. Esto se debe a que se agregan al contexto público resultante del módulo estándar.

Intercepción de métodos

La tarea de la intercepción de métodos, en la gran mayoría de los casos, es rodear la llamada del método estándar con ciertas acciones antes y/o después. No excluimos la opción de bloqueo completo de la llamada del método estándar e implementamos esta característica.

Puedes describir completamente la intercepción de un método estándar en el módulo que extiende una configuración estándar. Para hacer esto, hemos introducido un nuevo elemento estructural de 1C:Enterprise script: una anotación. Puedes usar una anotación ubicada antes de la declaración del método para especificar qué método estándar es interceptado por el procedimiento/función y cómo se hace. Por ejemplo:

&Before(“Procedure1”) Procedure Ext1_Proc1()     // Texto del procedimiento EndProcedure 

La anotación &Before (“Procedure1”) significa que se intercepta el procedimiento estándar llamado Procedure1. El nombre de la anotación “Before” significa que tu gancho Ext_Proc1() se ejecuta primero, seguido del Procedure1() estándar.

En este momento, hemos agregado tres posibles nombres de anotación a la plataforma.

Anotación &Before

Una anotación con este nombre significa que tu gancho se ejecuta antes de que comience la ejecución del método estándar.

En el diagrama, los rectángulos representan el módulo estándar y el módulo que extiende una configuración estándar, y la flecha muestra la secuencia de ejecución del script de 1C:Enterprise.

539ca7cd3658c1b760ebe956ae2679ca.png

Anotación &After

Esta anotación significa que tu gancho se ejecuta después de que se ejecute el método estándar.

7cf3964b47d4fb856bb07cc03f706476.png

Anotación &Around

Esta anotación es la que bloquea completamente el método estándar. Es decir, el método estándar no se ejecuta en absoluto. En su lugar, solo se ejecuta tu gancho.

010d6af94b4fa28956400e5a9ad5442d.png

Puedes establecer una de las siguientes combinaciones de gancho para un procedimiento estándar:

La última combinación de ganchos (&Before y &After) se ejecuta de la siguiente manera:

b1c337349e4e2ce4a6251d90f7a36b34.png

Si estás interceptando una función estándar en lugar de un procedimiento, solo puedes usar el gancho &Around.

Llamando a un método bloqueado por la anotación &Around

Lo que tenemos ahora parece injusto. Puedes bloquear o enmarcar un procedimiento. Sin embargo, en cuanto a una función, solo puedes bloquearla por completo.

Para abordar esta injusticia, implementamos un nuevo método para el script de 1C:Enterprise: ProceedWithCall(). Si llamas a este método dentro de tu función de gancho, se ejecuta la función que bloqueaste y luego la ejecución del script vuelve a tu gancho:

b96e2f0f0871ccfc0b9d1f02c115e449.png

En el script de 1C:Enterprise, esta función de gancho podría verse así:

&Around(“Standard”) Function Ext1_Function1(Param1)     // …     Var1 = ProceedWithCall(Param1);     // …     Return Var1; EndFunctionAsí, tu función de gancho se divide en dos partes. La parte que se ejecuta antes de la ejecución de la función estándar y la que se ejecuta después de la función estándar.

Puedes usar el método ProceedWithCall() no solo cuando bloqueas funciones, sino también cuando bloqueas procedimientos. En este caso, el resultado de su uso es el mismo que cuando se utiliza el par de ganchos &Before y &After. La única diferencia es que en este caso, tu parte “antes” y tu parte “después” existen dentro del mismo contexto. En algunas situaciones, puede ser útil. En el script de 1C:Enterprise, este gancho podría verse así:

&Around(“Procedure1”) Procedure Ext1_Proc1(Param1)     // …     Var1 = ProceedWithCall(Param1);     // … EndProcedure

¿Cuál es mejor: &Before, &After o &Around?

Cuando interceptas métodos de configuración estándar, siempre debes recordar dos cosas:

Desde esta perspectiva, es mejor usar los ganchos &Before y &After. Porque con ellos, el método estándar interceptado siempre se ejecuta sin ninguna condición. Si los desarrolladores de la configuración estándar realizan cambios en este método en algún momento posterior, estos cambios definitivamente tendrán efecto al usar tu extensión.

También puedes usar el gancho &Around y el método ProceedWithCall(). Pero aquí tienes la oportunidad y la tentación de llamar al método estándar no siempre, sino dependiendo de algunas de tus propias condiciones. Debes tener cuidado aquí y siempre recordar que cuando te abstienes de llamar al método estándar, te abstienes no solo de llamar al método que está presente en la configuración en ese momento, sino también de todas sus variaciones que aparecerán en el futuro. Sin embargo, en el futuro, la configuración puede actualizarse con cambios importantes y útiles.

Y finalmente, la opción “peor” es bloquear por completo el método estándar con el gancho &Around. En este caso, el controlador estándar no se ejecutará ahora ni en futuras versiones. Es decir, tú y tus extensiones asumen toda la responsabilidad del trabajo de las futuras versiones de la configuración. Ciertamente, hay situaciones en las que es necesario bloquear por completo, pero te animamos a que tomes esta decisión con cuidado y cautela.

Secuencia de llamadas para la intercepción de métodos

Antes de adentrarnos más en este tema, debemos aclarar algo primero. Una característica importante, por así decirlo, “ideológica” de las extensiones es su autonomía. Es decir, las extensiones deben diseñarse de tal manera que no dependan unas de otras.

Pero cuando una aplicación se está ejecutando, es natural y obvio que hay una cierta secuencia de llamadas para las extensiones adjuntas. Esta secuencia es conocida y te la diremos. Pero no te la diremos para que puedas usarla para crear extensiones interdependientes o extensiones con una única y estricta secuencia de adjuntos. Te la diremos para que puedas abordar los problemas que surjan y depurar el script.

Cuando adjuntas una extensión a una configuración estándar, se forma un “pastel de varias capas”. En la base de este pastel se encuentra la configuración estándar y en la parte superior se encuentra la última extensión adjunta.

Tanto en el Diseñador como en el modo 1C:Enterprise, la última extensión adjunta se muestra al final.

4b6a06f86f63a0213023babbc341f7d4.png

Así, en el ejemplo a continuación, la configuración estándar se encuentra en la parte inferior, la Extensión2 está en la parte superior y la Extensión1 está en el medio. Cada extensión posterior intercepta (extiende) lo que se encuentra debajo de ella.

Cuando la plataforma encuentra los ganchos definidos en las extensiones, el script de 1C:Enterprise se ejecuta de arriba a abajo del pastel de acuerdo con las anotaciones de los ganchos. Hasta el nivel al que puede llegar. Después de eso, vuelve hacia arriba si hay ganchos y luego vuelve a la configuración estándar.

Ejemplo 1

Por ejemplo, si el mismo método estándar es interceptado (enmarcado) en dos extensiones, la secuencia de llamadas de los controladores es la siguiente:

3f0d5c37c91c7dcf769699b639cc8157.png

Este ejemplo ilustra muy bien una peculiaridad: si en uno de los ganchos ocurre una excepción no procesada, se interrumpe toda la cadena y se escala la excepción.

Ejemplo 2

Si los ganchos utilizan el método ProceedWithCall(), se aplica el mismo principio del “pastel”.

4d9dbaca76ad90e9c6e0954561b45db3.png

Ejemplo 3

Es importante entender que cuando se utiliza la anotación &Around para bloquear un método, en realidad se bloquea no solo la llamada del método principal, sino también de los ganchos que se encuentran más abajo en el “pastel”.

73bc942634dbcfcef3476cd070b7c37c.png

En esto, solo se ejecuta el gancho &Around de la Extensión2. Esto se debe a que bloquea el método estándar (y todo el “pastel” que se encuentra debajo de él).

Ejemplo 4

En realidad, es una variación del segundo ejemplo, pero debajo de la extensión superior se encuentra la extensión que “baja” la llamada del procedimiento estándar.

a036ebbba79086ccc01c175774b4c595.png

En realidad, una vez más simplemente ilustra que llamar al método estándar se aplica a todo el “pastel” que se encuentra debajo de la extensión. Por eso, después de llamar al gancho de la Extensión2, se llama al gancho de la Extensión1. Porque bloquea la llamada del método estándar, al que la Extensión2 quiere “alcanzar”, en el “pastel” restante.

Interceptando controladores de eventos y agregando controladores personalizados a los módulos de objetos, gestores, etc.

Cualquier método en estos módulos se intercepta de la misma manera que se describe arriba. Sin embargo, si el procedimiento interceptado es un controlador de eventos, hay algunas peculiaridades de las que debes estar al tanto. Estas peculiaridades tienen que ver con el hecho de que en estos módulos, todos los controladores de eventos tienen nombres fijos.

En primer lugar, el nombre del evento se especifica como el nombre del método interceptado. Por ejemplo, BeforeWrite:

&After(“BeforeWrite”) Procedimiento Ext2_BeforeWrite(Cancel)     // Insertar código del controlador. EndProcedureEn segundo lugar, el controlador estándar para este evento no tiene que estar disponible. Si el controlador estándar no está disponible, se llama a tu gancho. Gracias a esta característica, puedes asignar controladores personalizados a los eventos que no se manejan en la configuración estándar.

Dado que los controladores de eventos tienen nombres fijos en los módulos de objetos, y conocemos la lista de anotaciones, podemos ofrecerte un cierto “servicio”. Cuando creas una extensión de controlador, se abre un cuadro de diálogo que te permite seleccionar el tipo de llamada. Luego, se crea una plantilla de gancho en el módulo.

f162942587d25e46498cb601fdd2dda4.png

Interceptando controladores de eventos y controladores personalizados en los módulos de formulario

Cualquier método en estos módulos también se intercepta de la misma manera que se describe arriba. Sin embargo, hay peculiaridades asociadas con la interceptación de controladores de eventos. Estas peculiaridades tienen que ver con el hecho de que en estos módulos, todos los controladores de eventos se asignan y no tienen nombres fijos. Como probablemente sabes, para que la plataforma sepa qué usar para manejar un evento, se debe asignar un procedimiento específico a un evento específico en una paleta de propiedades en Designer.

Es por esta razón y solo al interceptar controladores de eventos en los formularios, debes usar la paleta de propiedades en lugar de las anotaciones. Aunque puedes usar anotaciones para interceptar cualquier otro método de módulo que no sea un controlador de eventos.

Un gancho de evento en un módulo de formulario se ve así:

&AtServer Procedimiento Ext2_OnCreateAtServerAround(Cancel, ProcesamientoEstándar)     // Insertar código del controlador. EndProcedure 

Es decir, no se utiliza una anotación y se especifica el tipo de gancho en la paleta de propiedades. Se puede hacer fácilmente. Cuando creas un controlador en la extensión, al hacer clic en el botón “lupa” se abre un cuadro de diálogo. Te permite especificar, además del contexto, el tipo de gancho (Before, After o Around).

f63a66b3618bd464457a0a4e8fa5b0f0.png

Después de crear la plantilla de procedimiento en la paleta de propiedades, aparece un icono que representa el tipo de gancho junto al nombre del gancho.

e8e87285a03b367bd98b77b998880d4e.png

Si bloqueas el controlador estándar (Around), es solo un punto.

Si creas un gancho Before o After, es un punto junto a la línea vertical. La ubicación del punto antes o después de la línea denota el tipo de gancho. Además, aparece un segundo campo (vacío) junto a este evento en la paleta de propiedades. Puedes usarlo para establecer un gancho emparejado si es necesario enmarcar el controlador estándar con el par Before-After.

Los ganchos de eventos establecidos de esta manera funcionarán incluso si no hay un controlador estándar para este evento. Así es como puedes asignar controladores personalizados a los eventos de formulario que no se manejan en la configuración estándar.

Hablando de los módulos de formulario, nos gustaría señalar una cosa más. Hemos cambiado ligeramente el comportamiento de los módulos que extienden los módulos de formulario que existían anteriormente. Hicimos esto para que coincida con el comportamiento de otros módulos y garantizar la estabilidad del script.

Anteriormente, todos los módulos que extendían el módulo de formulario y el propio módulo de formulario estaban ubicados en el mismo espacio de nombres. Así, era posible llamar desde la extensión superior no solo a los métodos de la configuración estándar, sino también a los métodos que estaban ubicados debajo de las extensiones. Ahora hemos cerrado esta “laguna” y los métodos de las extensiones ubicadas debajo ya no están disponibles. Ahora solo puedes acceder a los métodos contenidos en el módulo estándar que estás extendiendo.

Módulos comunes

Puedes crear cualquier módulo común personalizado en una extensión. Solo hay dos restricciones:

Cuando extiendes un módulo estándar de una configuración estándar, te enfrentas a las mismas restricciones:

La operación de adoptar un módulo global del servidor no está prohibida en el árbol de configuración, pero al actualizar la configuración de la base de datos, recibirás un mensaje de error y la actualización fallará.

Los métodos del servidor no siempre se extienden

El hecho de que tu extensión se haya adjuntado correctamente a una configuración estándar no significa que todos los ganchos que tiene tu extensión se aplicarán y ejecutarán. Hay algunas peculiaridades relacionadas con la seguridad.

Si la aplicación funciona en modo de archivo o en modo cliente/servidor sin perfiles de seguridad, cuando adjuntas tu extensión:

Cuando una aplicación funciona en modo cliente/servidor y si se especifica un perfil de seguridad específico al adjuntar la extensión, o si se asignan perfiles de modo regular y seguro a la infobase, la parte “servidor” de la extensión se aplica según lo indicado en el perfil correspondiente.

Para esto, hemos agregado varias propiedades nuevas al perfil de seguridad.

b88e2ca12106cf5384f84fce67c2a9ab.png

La más simple de estas es la casilla de verificación all module extensions en el grupo Grant full access to. De un solo golpe, permite extender el contexto del servidor.

Hay una afinación más precisa disponible utilizando los campos Modules available for extension y Modules not available for extension. Suponemos que los utilizarás de la siguiente manera: