We are using IoC and have our logging exposed with it. We are using Common.Logging
and I have written a matching delegate for Common.Logging.FormatMessageHandler
but I do not know how to convert from our version of that delegate to the one that the Common.Logging
api is expecting.
This question appears to be similar but I do not understand how to convert from my implemented type to the known type that I want to call. Dynamically casting one type of delegate to another
Here is my delegate signature:
public delegate string FormatMessageHandler(string format, params object[] args)
Here is Common.Logging's:
public delegate string FormatMessageHandler(string format, params object[] args)
Same name (not that is matters) and same number of parameters. Both are known at compile time so it should be something obvious but I am not seeing it.
Manually you can do this, but it is as expensive as the reflection involved at conversion. Once the delegate is converted it behaves basically the same...
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);
}
Why are you not using Common.Logging's delegate in the first place if it is exactly the same?
However, a solution to your problem is to either use the dynamic cast explained in the article linked in the question you mentioned, or you do it like this:
YourNamespace.FormatMessageHandler yourHandler = ...;
Common.Logging.FormatMessageHandler handler = (f, a) => yourHandler(f, a);
UPDATE:
According to your comment, you want something like that:
public void Error(Action<Your.FormatMessageHandler> formatMessageCallback)
{
_logger.Error(h => formatMessageCallback((f, a) => h(f, a)));
}
This will create a new action with one parameter h
of type Common.Logging.FormatMessageHandler
which calls the supplied action formatMessageCallback
with a new delegate of Your.FormatMessageHandler
that accepts two parameters f
and a
. This new delegate in turn calls h
with the two supplied parameters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With