Можно ли реализовать реестр базовых методов на основе их типов? - PullRequest
1 голос
/ 22 февраля 2012

Вот мой делегат метода:

delegate void ExceptionHandelr<T>(T exception,out bool handeled) where T:Exception;

Я хотел бы иметь реестр такого рода методов, чтобы я мог вызывать их в зависимости от типа их методов, например:

var method=ErrorHandlers[typeof(NullReferenceException)];
method(exception as NullReferenceException,out handled);

Как я могу реализовать этот реестр? Я не могу иметь Dictionary<T,Method<T>> я могу?

Ответы [ 4 ]

2 голосов
/ 22 февраля 2012

Я бы сделал что-то вроде этого:

using System;
using System.Collections.Generic;
using System.Reflection;

namespace Test
{
    class MainApp
    {
        public class ExceptionRegistry
        {
            Dictionary<Type, object> registry = new Dictionary<Type, object>();

            private Func<T, bool> Get<T>() where T : Exception
            {
                return registry[typeof(T)] as Func<T, bool>;
            }

            private bool Invoke<T>(T exception) where T : Exception
            {
                return Get<T>().Invoke(exception);
            }

            public bool Invoke(Exception exception)
            {
                MethodInfo method = this.GetType().GetMethod("Invoke", BindingFlags.NonPublic | BindingFlags.Instance);
                MethodInfo generic = method.MakeGenericMethod(exception.GetType());
                var result = generic.Invoke(this, new object[] { exception });

                return (bool)result;
            }

            public void Add<T>(Func<T, bool> handler) where T : Exception
            {
                registry.Add(typeof(T), handler);
            }

        }

        static void Main()
        {
            ExceptionRegistry registry = new ExceptionRegistry();

            registry.Add<ArgumentException>((ArgumentException exception) =>
                {
                    // some logic

                    return true;
                });

            Exception ex = new ArgumentException();

            bool result = registry.Invoke(ex);
        }
    }
}
1 голос
/ 30 апреля 2013

Немного позднего ответа, но мне все равно хотелось его дать:)

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

public static class ExceptionHandlers<TEx>
    where TEx : Exception
{
    public static ExceptionHandler<TEx> Handle
    {
        get;
        set;
    }
}

Вы можете назначить обработчики в одном месте:

public static void MyExceptionHandler(MyException exception, out bool handled)
{
    // Handling logic...
}

...

ExceptionHandlers<MyException>.Handle = MyExceptionHandler;

... и использовать их там, где вам нужно:

try
{
    // Something...
}
catch(MyException myEx)
{
    bool handled;
    ExceptionHandlers<MyException>.Handle(myEx, out handled);
}

Один экземпляркаждый уникальный ExceptionHandler<TEx> создается во время выполнения, так как используются различные типы TEx, и при желании у вас есть обработчики без приведения:)

Было бы довольно легко расширить это решение для использованияколлекции обработчиков, если требуется.

1 голос
/ 22 февраля 2012

Я бы создал Dictionary<Type, Delegate>, а затем выполнил делегат, используя DynamicInvoke метод.

http://msdn.microsoft.com/en-us/library/system.delegate.dynamicinvoke.aspx

0 голосов
/ 25 февраля 2012

Можно иметь такой словарь, как вы описываете, но несколько лучше будет следовать примеру Comparer<T>. Реализуйте универсальный тип со статическим полем подходящего типа делегата вместе со средствами запроса поля или установки его, если он еще не установлен. При желании вы могли бы даже иметь значение по умолчанию для поля как подпрограмму, которая проверила бы тип, чтобы увидеть, реализует ли он некоторый интерфейс, и заставила бы делегат указывать на метод интерфейса, если это необходимо.

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