是否可以根据其类型实现泛型方法的注册表?

时间:2012-02-22 12:53:09

标签: c# generics delegates

这是我拥有的方法委托:

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 个答案:

答案 0 :(得分:2)

我会做这样的事情:

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 :(得分:1)

我会创建Dictionary<Type, Delegate>并使用DynamicInvoke方法执行委托。

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

答案 2 :(得分:1)

有点迟到的答案,但无论如何我还是觉得给它:)

您可以使用静态通用帮助程序类以强类型,类型安全的方式存储和检索处理程序:

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类型,并且根据需要,您可以使用没有转换的处理程序:)

如果需要,扩展此解决方案以使用处理程序集合也很容易。

答案 3 :(得分:0)

可以有一个如你所描述的字典,但更好的模式是跟随Comparer<T>的引导。使用适当委托类型的静态字段实现泛型类型,以及查询字段的方法,或者如果尚未设置字段则设置它。如果需要,您甚至可以将字段的默认值作为例程来检查类型以查看它是否实现了某个接口,并在适当时使委托指向接口方法。

相关问题