Primero de todo, ¿qué es esto de las Nested classes o Clases anidadas? Hablamos de este concepto, en este caso, para referirnos a controles de formularios, datasources de formularios, campos de un datasource de un formulario, etc… ¿Pero por qué lo llamamos así? Pues una forma sencilla de verlo es dirigirnos a algún formulario de #MSDyn365FO, por ejemplo, al CustTable, y ver su código. En el, podremos ver que el formulario CustTable es una clase, que tiene dentro uno o varios DataSources, que son a su vez clases que contienen DataFields, que también son clases, por lo que nos encontramos con clases dentro de clases, o clases anidadas.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[Form] public class CustTable extends FormRun { const str address = 'Address'; const str addressTab = 'AddressTab'; ... [DataSource] class CustTable { .... [DataField] class CashDisc { .... } } } |
Visto esto, os recuerdo como podíamos modificar propiedades de FormControls en #MSDyn365FO a través de manejadores de eventos (Event handlers), de forma que podíamos cambiar el comportamiento o las propiedades de dicho control en tiempo de ejecución. En ese momento, la única posibilidad que teníamos para realizar dicha tarea era esa, suscribirnos al evento en cuestión, obtener el control que queríamos editar, y modificar sus propiedades.
A día de hoy, podemos hacer este tipo de modificaciones de forma más rápida y sencilla, ya que podemos extender la funcionalidad por medio de Chain Of Command (CoC) sobre clases anidadas, o lo que es lo mismo, aplicar Chain Of Command sobre controles de formularios (FormControls), orígenes de datos (FormDataSources) y controles en general como botones o campos de datos (FormDataFields) del propio formulario. ¿Y cómo hacemos esto?. Pues muy fácil, supongamos que queremos modificar alguna propiedad de un DataSource concreto en tiempo de ejecución. De momento, nos olvidamos de los Event Handlers, y vamos directamente al lío:
1- Creamos una clase, que debe ser de tipo final y será la extensión FormDataSource en sí, y le añadimos el atributo ExtensionOf que indicará el objeto que estamos extendiendo.
1 2 3 4 |
[ExtensionOf(formDatasourceStr(CustTable, CustTable))] final class CustTableJATM_Extension { } |
2- Añadimos el método active, que debe tener la misma definición que el método estándar. En este método tenemos que llamar al método next() obligatoriamente, que se encargará de ejecutar el código estándar del método. Es un concepto similar al de super().
1 2 3 4 5 6 7 8 9 |
[ExtensionOf(formDatasourceStr(CustTable, CustTable))] final class CustTableJATM_Extension { public int active() { int ret = next active(); return ret; } } |
3- Ahora ya añadimos el código necesario para llevar a cabo nuestro propósito.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[ExtensionOf(formDatasourceStr(CustTable, CustTable))] final class CustTableJATM_Extension { public int active() { int ret = next active(); FormDataSource custTableDS = this; custTableDS.allowEdit("condición"); return ret; } } |
La primera gran diferencia que vemos con respecto a los event handlers, es que podemos acceder al objeto en cuestión utilizando el this, eso sí, si necesitamos modificar alguna propiedad tenemos que asignarlo a una variable de ese tipo para poder acceder a sus propiedades.
La verdad que la entrada del Chain of Command dentro de la plataforma nos facilita muchísimo la tarea de extender la funcionalidad del sistema, y eso es de agradecer. (Por ejemplo, y aunque no tiene que ver con los nested classes, mientras que solo podíamos suscribirnos a eventos de métodos públicos, Chain of Command nos permite extender la funcionalidad de métodos tanto públicos como protegidos).
Como comentaba anteriormente, podemos extender implementando Chain of Command tanto FormDataSources como FormControls y FormDataFields, utilizando los métodos formDatasourceStr(), formControlStr() y formDatafieldStr() respectivamente para identificar el objeto que estamos extendiendo.
Y hasta aquí el artículo de hoy, os leo en los comentarios. 🙂