2011-07-05 8 views
8

Estamos usando IoC y tenemos nuestro registro expuesto con él. Estamos utilizando Common.Logging y he escrito un delegado correspondiente para Common.Logging.FormatMessageHandler, pero no sé cómo convertir de nuestra versión de ese delegado al que espera la API Common.Logging.Convierta de un delegado a otro. Pseudo-molde

Esta pregunta parece ser similar pero no entiendo cómo convertir de mi tipo implementado al tipo conocido que deseo llamar. Dynamically casting one type of delegate to another

Aquí es mi delegado de la firma:

public delegate string FormatMessageHandler(string format, params object[] args) 

Aquí es Common.Logging de:

public delegate string FormatMessageHandler(string format, params object[] args) 

mismo nombre (no es materia) y el mismo número de parámetros. Ambos son conocidos en tiempo de compilación, por lo que debería ser algo obvio, pero no lo estoy viendo.

Respuesta

7

¿Por qué no está utilizando el delegado de Common.Logging en primer lugar si es exactamente igual?
Sin embargo, un solition a su problema es para cualquiera que use el elenco dinámico explica en el artículo enlazado en la pregunta que usted ha mencionado, o que lo haga de esta manera:

YourNamespace.FormatMessageHandler yourHandler = ...; 
Common.Logging.FormatMessageHandler handler = (f, a) => yourHandler(f, a); 

ACTUALIZACIÓN:
De acuerdo con su Comentario, desea algo así:

public void Error(Action<Your.FormatMessageHandler> formatMessageCallback) 
{ 
    _logger.Error(h => formatMessageCallback((f, a) => h(f, a))); 
} 

Esto creará una nueva acción con un parámetro de tipo hCommon.Logging.FormatMessageHandler que llama a la acción suministrado formatMessageCallback con un nuevo delegado de Your.FormatMessageHandler que acepta dos parámetros f y a. Este nuevo delegado a su vez llama al h con los dos parámetros proporcionados.

+0

Su explicar es grande y funciona hasta que intento utilizar la acción . ¿Cómo puedo hacerlo con Action? Mi método de firma: pública error nula (Acción formatMessageCallback) Y el último método para llamar es: vacío Common.Logging.Error (Acción formatMessageCallback); –

+0

No expongo el delegado Common.Logging ni ninguna de las API en caso de que decidamos usar un marco de registro diferente en el futuro. Si eso sucede, entonces "todo" lo que tenemos que hacer es escribir algún código que implemente la interfaz de registro que definimos antes y envolver las llamadas al nuevo marco de registro. –

+0

@David: La razón para no usar el delegado del registrador es válida, gracias por explicarnos. Por favor, mira la actualización para encontrar una solución a tu primer comentario. –

1

Manualmente puede hacerlo, pero es tan caro como la reflexión que implica la conversión. Una vez que se convierte el delegado se comporta básicamente el mismo ...

internal class Program 
{ 
    //An example delegate target 
    static void Click(object o, EventArgs e) { } 

    //A simple test method 
    static void Main(string[] args) 
    { 
     EventHandler onclick = Click; 
     EventHandler<EventArgs> converted; 
     if (!TryConvertDelegate(onclick, out converted)) 
      throw new Exception("failed"); 
    } 

    //The conversion of one delegate type to another 
    static bool TryConvertDelegate<TOldType, TNewType>(TOldType oldDelegate, out TNewType newDelegate) 
     where TOldType : class, System.ICloneable, System.Runtime.Serialization.ISerializable 
     where TNewType : class, System.ICloneable, System.Runtime.Serialization.ISerializable 
    { 
     if (!typeof(Delegate).IsAssignableFrom(typeof(TOldType)) || !typeof(Delegate).IsAssignableFrom(typeof(TNewType))) 
      throw new ArgumentException(); //one of the types is not a delegate 

     newDelegate = default(TNewType); 
     Delegate handler = oldDelegate as System.Delegate; 
     if (handler == null) 
      return true; //null in, null out 

     Delegate result = null; 
     foreach (Delegate d in handler.GetInvocationList()) 
     { 
      object copy = System.Delegate.CreateDelegate(typeof(TNewType), d.Target, d.Method, false); 
      if (copy == null) 
       return false; // one or more can not be converted 
      result = System.Delegate.Combine(result, (System.Delegate)copy); 
     } 
     newDelegate = result as TNewType; 
     return (newDelegate != null); 
    } 
Cuestiones relacionadas