C#中如何仅通过异常名称字符串实例化并抛出对应异常
C#通过字符串异常名称实例化并抛出异常的实现方案
直接通过字符串类名执行new操作是不被C#语法支持的,你可以根据项目场景选择以下两种可行方案:
方案1:反射动态加载类型(适合异常种类动态扩展的场景)
核心逻辑是通过反射根据字符串类名查找对应的异常类型,再调用构造函数创建实例后抛出,实现步骤如下:
- 先确定所有自定义异常所在的命名空间、所属程序集,拼接出类型的完整名称
- 校验加载到的类型是否为
Exception的子类,避免加载无效类型 - 匹配异常类的构造函数(优先支持传入自定义错误消息的构造,回退到无参构造)
- 创建实例后直接抛出
完整实现代码:
using System; using System.Reflection; public static class ExceptionThrower { // 替换为你项目中异常类所在的命名空间 private const string ExceptionNamespace = "YourProject.Exceptions"; // 替换为异常类所在的程序集,示例中取当前类所在程序集 private static readonly Assembly ExceptionAssembly = typeof(ExceptionThrower).Assembly; public static void Throw(string exceptionName, string message = null) { // 拼接类型全名称 string fullType = $"{ExceptionNamespace}.{exceptionName}"; Type exType = ExceptionAssembly.GetType(fullType); // 校验类型有效性 if (exType == null || !typeof(Exception).IsAssignableFrom(exType)) { throw new ArgumentOutOfRangeException(nameof(exceptionName), $"无效的异常名称:{exceptionName}"); } Exception exInstance; // 优先使用带string消息参数的构造函数 if (!string.IsNullOrEmpty(message)) { ConstructorInfo msgCtor = exType.GetConstructor(new[] { typeof(string) }); if (msgCtor != null) { exInstance = (Exception)msgCtor.Invoke(new object[] { message }); throw exInstance; } } // 无消息时使用无参构造 exInstance = (Exception)Activator.CreateInstance(exType); throw exInstance; } }
调用示例:
string myException = "ConflictException"; ExceptionThrower.Throw(myException, "当前资源状态冲突,操作失败");
方案2:预定义工厂映射字典(适合异常种类固定的场景)
如果你的异常集合是固定的,优先用字典做名称到异常工厂的映射,相比反射性能更高、类型更安全,不会出现命名空间不匹配、构造函数缺失的运行时问题:
using System; using System.Collections.Generic; public static class ExceptionThrower { private static readonly Dictionary<string, Func<string, Exception>> _exFactories = new() { ["ConflictException"] = msg => new ConflictException(msg), ["InternalServerErrorException"] = msg => new InternalServerErrorException(msg), // 新增异常时只需在这里添加对应映射即可 }; public static void Throw(string exceptionName, string message = null) { if (!_exFactories.TryGetValue(exceptionName, out var factory)) { throw new ArgumentOutOfRangeException(nameof(exceptionName), $"无效的异常名称:{exceptionName}"); } throw factory(message ?? "服务发生未知错误"); } }
注意事项
- 如果你的异常分布在多个不同程序集,反射方案中需要遍历当前应用域已加载的所有程序集查找目标类型,不要仅限定单个程序集
- 无论使用哪种方案,都必须校验最终生成的对象是
Exception的子类,否则抛出时会触发运行时错误 - 如果你的自定义异常需要额外构造参数(如错误码、内部异常对象),可以对应调整构造函数传参逻辑或工厂方法的入参
内容的提问来源于stack exchange,提问作者McArthey
相关产品推荐
相关产品推荐

