SqlException 的构造函数在哪里?

Where is constructor of SqlException?

我正在编写单元测试以验证是否检测到数据库过载引起的异常。

但是我找不到 SqlException 的构造函数。为什么我在元数据中看不到构造函数?

以下代码只是为了帮助理解我为什么要寻找构造函数。

#region Is Timeout
[TestMethod]
public void TestTimeOutWin32ExceptionTimeOut()
{
    Win32Exception ex = new Win32Exception("The wait operation timed out");
    Assert.IsTrue(ExceptionHelper.IsDatabaseTimeOut(ex));
}

[TestMethod]
public void TestTimeOutSqlExceptionTimeOut()
{
    SqlException ex = new SqlException("Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.");
    Assert.IsTrue(ExceptionHelper.IsDatabaseTimeOut(ex));
}

[TestMethod]
public void TestTimeOutEntityCommandExecutionException()
{
    SqlException innerException = new SqlException("Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.");
    EntityCommandExecutionException ex = new EntityCommandExecutionException("anything", innerException);
    Assert.IsTrue(ExceptionHelper.IsDatabaseTimeOut(ex));
}

#endregion

#region Is NOT Timeout
[TestMethod]
public void TestTimeOutWin32ExceptionEmpty()
{
    Win32Exception ex = new Win32Exception("");
    Assert.IsFalse(ExceptionHelper.IsDatabaseTimeOut(ex));
}

[TestMethod]
public void TestTimeOutArgumenException()
{
    ArgumentException ex = new ArgumentException("invalid path");
    Assert.IsFalse(ExceptionHelper.IsDatabaseTimeOut(ex));
}

[TestMethod]
public void TestTimeOutArgumenNullException()
{
    ArgumentNullException ex = new ArgumentNullException("empty path");
    Assert.IsFalse(ExceptionHelper.IsDatabaseTimeOut(ex));
}

[TestMethod]
public void TestTimeOutException()
{
    Exception ex = new Exception("custom string");
    Assert.IsFalse(ExceptionHelper.IsDatabaseTimeOut(ex));
}
#endregion

我不知道他们为什么没有提供 public 构造函数,但您可以使用 FormatterServices.GetUninitializedObject

创建一个实例
var sqlex = FormatterServices.GetUninitializedObject(typeof(SqlException)) as SqlException;

之后您可以使用 FormatterServices.PopulateObjectMembers 来填充您想要的成员。

提示:小心!

根据 hvd 评论编辑:

但为什么要自己做呢?强制 SQL 服务器超时一次,序列化异常,将序列化的异常存储在测试数据中,在需要特定异常时反序列化它。

是的,构造函数是私有的:

private SqlException CreateSqlException(string message)
{
        var collectionConstructor = typeof(SqlErrorCollection).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, //visibility
            null, //binder
            new Type[0],
            null);          

        var errorCollection = (SqlErrorCollection)collectionConstructor.Invoke(null);

        var constructor = typeof(SqlException).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, //visibility
            null, //binder
            new[] { typeof(string), typeof(SqlErrorCollection), typeof(Exception), typeof(Guid) },
            null); //param modifiers

        return (SqlException)constructor.Invoke(new object[] { message, errorCollection, new DataException(), Guid.NewGuid() });
}

取自jgauffin's coding den

SqlException 使用内部工厂方法 (CreateException) 通过私有构造函数在内部创建实例。没有 public 方法允许您创建一个,可能是因为它特定于 SQL 数据提供程序,而不是让您创建自己的异常。