使用派生类型

时间:2018-06-01 10:34:22

标签: c# casting extension-methods

简化,我有这两个Extension方法:

public static class Extensions
{
    public static string GetString(this Exception e)
    {
        return "Standard!!!";
    }
    public static string GetString(this TimeoutException e)
    {
        return "TimeOut!!!";
    }
}

以下是我使用它们的地方:

try
{
    throw new TimeoutException();
}
catch (Exception e)
{
    Type t = e.GetType(); //At debugging this a TimeoutException
    Console.WriteLine(e.GetString()); //Prints: Standard
}

我有更多GetString()个扩展名。

我的try{...}catch{...}变得越来越大,基本上我在寻找方法将它缩短为1个根据异常类型调用扩展名的catch。

有没有办法在运行时调用正确的扩展方法?

2 个答案:

答案 0 :(得分:4)

正如Yacoub Massad建议您可以使用dynamic,因为使用dynamic方法重载决议在运行时通过后期绑定延迟。:

public static class Extensions
{
    public static string GetString<T>(this T e) where T : Exception
    {
        // dynamic method overload resolution is deferred at runtime through late binding.
        return GetStringCore((dynamic)e);
    }

    static string GetStringCore(Exception e)
    {
        return "Standard!!!";
    }

    static string GetStringCore(TimeoutException e)
    {
        return "TimeOut!!!";
    }

    static string GetStringCore(InvalidOperationException e)
    {
        return "Invalid!!!";
    }
}

这应该成功。

答案 1 :(得分:-1)

扩展方法在这里是错误的工具。

我会促进使用多态来解决你的问题:

public abstract class BaseException : Exception
{
    public abstract string GetString();
}

public sealed class TimeoutException : BaseException
{
    public override string GetString() => "TimeOut!!!";
}

public sealed class MyException : BaseException
{
    public override string GetString() => "Standard!!!";
}

用法

try
{
    throw new TimeoutException(); //or whatever BaseException's children
}
catch (BaseException e)
{
    //here I'm assuming you know that you are swallowing the exception (which may be an anti-pattern)
    Console.WriteLine(e.GetString());
}

修改

看起来你无法完全控制抛出异常的时间。另一种可能性是为每个行为添加1个catch子句(而不是每个异常类型)并删除GetString()

try
{
    throw new TimeoutException();
}
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
    //do something
}
catch (Exception e) when (e is TimeoutException)
{
    //do something
}
catch (Exception e)
{
    throw new NotImplementedException($"Hey Mike, write something for {e.GetType()}, will ya?"); //idea from Jeroen
}