Преобразование из одного делегата в другого.Псевдо актерский состав - PullRequest
9 голосов
/ 06 июля 2011

Мы используем IoC, и наши журналы выставляются вместе с ним. Мы используем Common.Logging, и я написал соответствующий делегат для Common.Logging.FormatMessageHandler, но я не знаю, как преобразовать нашу версию этого делегата в ту, которую ожидает Common.Logging api.

Этот вопрос кажется похожим, но я не понимаю, как преобразовать из моего реализованного типа в известный тип, который я хочу вызвать. Динамическое приведение одного типа делегата к другому

Вот моя подпись делегата:

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

Вот Common.Logging's:

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

То же имя (не это имеет значение) и такое же количество параметров. Оба они известны во время компиляции, поэтому это должно быть что-то очевидное, но я этого не вижу.

Ответы [ 2 ]

8 голосов
/ 06 июля 2011

Почему вы не используете делегат Common.Logging, если он точно такой же?
Однако решение вашей проблемы - либо использовать динамическое приведение, описанное в статье, связанной с упомянутым вами вопросом, либо сделать это следующим образом:

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

UPDATE:
Согласно вашему комментарию, вы хотите что-то подобное:

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

Это создаст новое действие с одним параметром h типа Common.Logging.FormatMessageHandler, которое вызывает предоставленное действие formatMessageCallback с новым делегатом Your.FormatMessageHandler, который принимает два параметра f и a. Этот новый делегат, в свою очередь, вызывает h с двумя предоставленными параметрами.

1 голос
/ 06 июля 2011

Вручную вы можете сделать это, но это так же дорого, как отражение при конвертации. Как только делегат преобразован, он ведет себя в основном так же ...

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);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...