Combinar delegados: ¿Cómo verificar si un delegado multicast (combinable) ya tiene un delegado dentro de él?
Estoy utilizando Unity 3D, sin embargo, esa información no debería ser relevante para resolver este problema, ya que el problema central es System.Delegate (quería hacértelo saber ya que estaré enlazando a algunos documentos de Unity para aclarar).
Tengo una ventana personalizada que tiene una función de actualización personalizada llamada “DirectorUpdate”. Necesito que esta función se ejecute en cada actualización del editor sin importar lo que esté haciendo el usuario/ventana.
Para que esto se llame en cada actualización del editor, combino mi método con el Delegado EditorApplication.update (https://docs.unity3d.com/ScriptReference/EditorApplication-update.html):
“`C#
protected void OnEnable()
{
// Si hago lo siguiente, la función base EditorApplication.update ya no se llamará.
// EditorApplication.update = this.DirectorUpdate;
// Así que necesito hacer esto:
EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
<pre><code>… // Otras cosas
</code></pre>
}
“`
Ten en cuenta que esto se hace dentro de un OnEnable
de una ventana (https://docs.unity3d.com/ScriptReference/ScriptableObject.OnEnable.html).
El problema es que OnEnable puede ser llamado más de una vez durante una sola ejecución (por ejemplo, al cerrar la ventana y luego volver a abrirla durante una sesión de editor única), lo que provoca que la línea EditorApplication.update = (EditorApplication.CallbackFunction)System.Delegate.Combine(new EditorApplication.CallbackFunction(this.DirectorUpdate), EditorApplication.update);
se llame varias veces, lo que significa que mi método de actualización (this.DirectorUpdate)
eventualmente se llamará varias veces por actualización, lo que está causando algunos errores graves.
Entonces, la pregunta es ¿cómo puedo verificar si EditorApplication.update ya tiene mi método “dentro” de él? (Cuando digo “dentro” me refiero a que ya se ha combinado System.Delegate.Combine(d)
en el delegado).
Soy consciente de que podría haber otras soluciones, por ejemplo, restaurar EditorApplication.update a lo que era antes cuando se cierra la ventana, sin embargo, eso no tendrá en cuenta todas las situaciones (por ejemplo, OnEnable también se llama durante la actualización de la ventana, entre otras cosas) y el error persistirá. (Además, ¿qué sucede si otra ventana se combina con EditorApplication.update mientras esta ventana está abierta?) Por lo tanto, la mejor solución sería verificar si EditorApplication.update ya está llamando a este método ANTES de combinarlo con Delegate.Combine.
davy.ai
Para verificar si
EditorApplication.update
ya tiene el métodothis.DirectorUpdate
dentro de él, puedes usar el métodoDelegate.GetInvocationList()
para obtener un array de delegados actualmente en el delegado multicastEditorApplication.update
. Luego, puedes recorrer este array y comparar cada delegado conthis.DirectorUpdate
utilizando el métodoDelegate.Equals()
. Si se encuentra una coincidencia, sabrás que el método ya está suscrito al delegado y no es necesario agregarlo nuevamente.Aquí tienes una implementación de ejemplo de esta verificación:
Este código primero obtiene el array de delegados en
EditorApplication.update
, luego recorre cada delegado para verificar si es el mismo quethis.DirectorUpdate
. Si se encuentra una coincidencia, se establecedelegateAlreadyAdded
en true y se sale del bucle. Si no se encuentra ninguna coincidencia,delegateAlreadyAdded
permanece en false y el nuevo delegado se concatena aEditorApplication.update
.Al utilizar esta verificación, puedes evitar agregar el mismo método a
EditorApplication.update
varias veces y prevenir los errores que pueden surgir al suscribir el mismo método múltiples veces.