Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否可以根据泛型方法的类型实现泛型方法注册表?_C#_Generics_Delegates - Fatal编程技术网

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

C# 是否可以根据泛型方法的类型实现泛型方法注册表?,c#,generics,delegates,C#,Generics,Delegates,我有一个方法委托: delegate void ExceptionHandelr<T>(T exception,out bool handeled) where T:Exception; 如何实现此注册表?我不能有字典,可以吗 我会创建一个字典,然后使用DynamicVoke方法执行委托 我将创建一个字典,然后使用DynamicVoke方法执行委托 我会这样做: using System; using System.Collections.Generic; using System

我有一个方法委托:

delegate void ExceptionHandelr<T>(T exception,out bool handeled) where T:Exception;
如何实现此注册表?我不能有字典,可以吗

我会创建一个字典,然后使用DynamicVoke方法执行委托

我将创建一个字典,然后使用DynamicVoke方法执行委托


我会这样做:

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);
        }
    }
}

我会这样做:

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);
        }
    }
}

你可以有一本你描述的字典,但更好的模式是遵循Comparer的指导。使用合适委托类型的静态字段实现泛型类型,以及查询字段或设置字段(如果尚未设置)的方法。如果需要,您甚至可以将该字段的默认值设置为一个例程,该例程将检查该类型是否实现了某个接口,并在适当的情况下使委托指向接口方法。

可以使用您描述的字典,但更好的模式是遵循Comparer。使用合适委托类型的静态字段实现泛型类型,以及查询字段或设置字段(如果尚未设置)的方法。如果需要,您甚至可以将该字段的默认值设置为一个例程,该例程将检查该类型是否实现了某些接口,并在适当的情况下使委托指向接口方法。

回答有点晚,但我还是希望给出它:

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

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);
}
当使用不同的TEx类型时,会在运行时创建每个唯一ExceptionHandler的单个实例,并且根据需要,您已经获得了无强制转换的处理程序:


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

回答有点晚,但我还是希望给出它:

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

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);
}
当使用不同的TEx类型时,会在运行时创建每个唯一ExceptionHandler的单个实例,并且根据需要,您已经获得了无强制转换的处理程序:



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

感谢您的重播。这种方法会让我的代码相当难看:有没有办法将一个委托转换为一个特定的委托?@Beatles1692-我不会说它难看。这就是当你使用“太多”泛型时你得到的结果-我以为我们使用泛型来摆脱强制转换,但似乎我们不能:问题是Foo和Foo没有可以在代码中使用的通用“基类型”…感谢您的重播。这种方法会让我的代码相当难看:有没有办法将一个委托转换为一个特定的委托?@Beatles1692-我不会说它难看。这就是当你使用“太多”泛型时你得到的结果-我以为我们使用泛型来摆脱强制转换,但似乎我们不能:问题是Foo和Foo没有可以在代码中使用的通用“基类型”…那么我们就不再使用泛型方法委托了:不,你没有。。但这是一个问题吗?一般来说不是,但我想了解更多关于泛型方法的信息。实际上,我想使用Lambda表达式定义我的方法,我不想在我的方法体中抛出异常。谢谢!干得好:但是我认为如果我们在Invoke方法中不提及异常类型会更好。只需调用Registry.invokeeexception然后我们就不再使用泛型方法委托了:不,你没有。。但这是一个问题吗?一般来说不是,但我想了解更多关于泛型方法的信息。实际上,我想使用Lambda表达式定义我的方法,我不想在我的方法体中抛出异常。谢谢!很好的工作:但是我认为如果我们不在Invoke方法中提到异常类型会更好。只需调用Registry.invokeexception你能给我看一些我没有完全掌握的代码吗:你能给我看一些我没有完全掌握的代码吗:使用静态类作为持有者是一个很好的方法。另外两种填充方法是:1在泛型类上有一个新的约束,并使接口包含一个工厂方法,该方法将生成另一个根据指定参数初始化的实例,或者包含一个方法,该方法将返回一个可能的单例工厂,该工厂可以生成具有指定参数的实例,或者2让ExceptionHandler的构造函数检查类型TEx是否有静态方法ExceptionHandler GetExceptionHandler,如果有,则缓存该方法。请注意,让静态类构造函数抛出异常是非常糟糕的形式。如果反射找不到su
方法,它应该设置一些字段,以便在代码尝试使用缓存值时引发异常。或者,获取异常处理程序的属性可以在第一次调用它时使用反射,然后返回一个缓存值。有很多方法可以使用,但是我们应该努力确保任何将被抛出的异常在不早也不晚的时候被抛出。所有有趣的建议:使用静态类作为持有者是一种很好的方法。另外两种填充方法是:1在泛型类上有一个新的约束,并使接口包含一个工厂方法,该方法将生成另一个根据指定参数初始化的实例,或者包含一个方法,该方法将返回一个可能的单例工厂,该工厂可以生成具有指定参数的实例,或者2让ExceptionHandler的构造函数检查类型TEx是否有静态方法ExceptionHandler GetExceptionHandler,如果有,则缓存该方法。请注意,让静态类构造函数抛出异常是非常糟糕的形式。如果反射找不到合适的方法,它应该设置一些字段,以便在代码尝试使用缓存值时引发异常。或者,获取异常处理程序的属性可以在第一次调用它时使用反射,然后返回一个缓存值。我们可以使用多种方法,但我们应该努力确保将抛出的任何异常都不会早晚被抛出。所有有趣的建议: