将动态对象传递给 .NET 6 中的自定义内插字符串处理程序时出现无效实例化异常
Invalid instantiation exception when pass dynamic object to custom interpolated string handler in .NET 6
我发现在我的记录器方法中升级到 .NET 6 LogErrorInterpolatedStringHandler
时出现问题。
这里是经典方法:
public static void Log(string message, params object[] pars)
{
// Log message
}
这是升级版:
public static void Log(ref LogErrorInterpolatedStringHandler message, params object[] pars)
{
// Log message
}
我升级了方法以获得 C# 10 和 .NET 6 所述的性能改进 here。
除了在内插字符串中传递 dynamic
对象外,新版本的方法运行良好。
这是一个例子:
// Works well
Logger.Log($"Log: {stringOrEverythingElseObject}");
// Exception
Logger.Log($"Log: {dynamicObject}");
抛出的异常是
The generic type '<>A{00000004}`3' was used with an invalid instantiation in assembly 'MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
我发现 a pull request 与我的问题类似,但无法理解如何在我的代码中修复。
你有什么想法吗?
谢谢!
TL;DR
除了在调用站点将 dynamicObject
转换为 object
之外,您无能为力:
Logger.Log($"Log: {(object)dynamicObject}");
或从处理程序中删除 ref
:
[InterpolatedStringHandler]
public struct LogErrorInterpolatedStringHandler
但不确定它会如何影响性能(尽管使用 dynamic
对性能的影响应该比这大得多,通常你应该避免在性能敏感代码中使用 dynamic
)
尝试解释
由于 following limitation:,ref struct
不能很好地与 dynamic
一起使用
- A
ref
struct can't be a type argument.
虽然处理 dynamic
的代码使用相关类型作为类型参数。 IE。以下代码:
var handler = new Handler();
handler.AppendFormatted((dynamic)5);
ref struct Handler
{
// or public void AppendFormatted<T>(T value) { }
public void AppendFormatted(object value) { }
}
会产生这样的结果 generated by compiler:
private static class <>o__0
{
public static CallSite<<>A{00000002}<CallSite, Handler, object>> <>p__0;
}
注意类型参数列表中的 Handler
,这将导致完全相同的运行时错误。从处理程序中删除 ref
可以解决问题。
如本 test comments and this comment by Stephen Toub 中所述,当前 Roslyn 在运行时失败时不会为此代码发出任何构建时错误。
我发现在我的记录器方法中升级到 .NET 6 LogErrorInterpolatedStringHandler
时出现问题。
这里是经典方法:
public static void Log(string message, params object[] pars)
{
// Log message
}
这是升级版:
public static void Log(ref LogErrorInterpolatedStringHandler message, params object[] pars)
{
// Log message
}
我升级了方法以获得 C# 10 和 .NET 6 所述的性能改进 here。
除了在内插字符串中传递 dynamic
对象外,新版本的方法运行良好。
这是一个例子:
// Works well
Logger.Log($"Log: {stringOrEverythingElseObject}");
// Exception
Logger.Log($"Log: {dynamicObject}");
抛出的异常是
The generic type '<>A{00000004}`3' was used with an invalid instantiation in assembly 'MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
我发现 a pull request 与我的问题类似,但无法理解如何在我的代码中修复。
你有什么想法吗? 谢谢!
TL;DR
除了在调用站点将 dynamicObject
转换为 object
之外,您无能为力:
Logger.Log($"Log: {(object)dynamicObject}");
或从处理程序中删除 ref
:
[InterpolatedStringHandler]
public struct LogErrorInterpolatedStringHandler
但不确定它会如何影响性能(尽管使用 dynamic
对性能的影响应该比这大得多,通常你应该避免在性能敏感代码中使用 dynamic
)
尝试解释
由于 following limitation:,ref struct
不能很好地与 dynamic
一起使用
- A
ref
struct can't be a type argument.
虽然处理 dynamic
的代码使用相关类型作为类型参数。 IE。以下代码:
var handler = new Handler();
handler.AppendFormatted((dynamic)5);
ref struct Handler
{
// or public void AppendFormatted<T>(T value) { }
public void AppendFormatted(object value) { }
}
会产生这样的结果 generated by compiler:
private static class <>o__0
{
public static CallSite<<>A{00000002}<CallSite, Handler, object>> <>p__0;
}
注意类型参数列表中的 Handler
,这将导致完全相同的运行时错误。从处理程序中删除 ref
可以解决问题。
如本 test comments and this comment by Stephen Toub 中所述,当前 Roslyn 在运行时失败时不会为此代码发出任何构建时错误。