简体   繁体   中英

Invalid instantiation exception when pass dynamic object to custom interpolated string handler in .NET 6

I found an issue upgrading to the .NET 6 LogErrorInterpolatedStringHandler in my logger method.

Here is the classic method:

public static void Log(string message, params object[] pars)
{
    // Log message
}

and here is the upgraded one:

public static void Log(ref LogErrorInterpolatedStringHandler message, params object[] pars)
{
    // Log message
}

I upgraded the method in order to get the performance improvements of C# 10 and .NET 6 described here .

The new version of the method works well except when passing dynamic object in the interpolated string.

Here is an example:

// Works well   
Logger.Log($"Log: {stringOrEverythingElseObject}");

// Exception
Logger.Log($"Log: {dynamicObject}");

The exception thrown is

The generic type '<>A{00000004}`3' was used with an invalid instantiation in assembly 'MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

I found a pull request similar to my problem but could not understand how to fix in my code.

Do you have any idea? Thanks

TL;DR

There is not much you can do except casting dynamicObject to object at the call site:

Logger.Log($"Log: {(object)dynamicObject}");

or removing ref from the handler:

[InterpolatedStringHandler]
public struct LogErrorInterpolatedStringHandler

But not sure how it will affect performance (though using dynamic should have much more effect on performance than this, in general you should avoid dynamic in performance sensitive code)

Attempt to explain

ref struct s do not work with dynamic very well due to the following limitation :

  • A ref struct can't be a type argument.

While code handling the dynamic uses the related types as type parameters. Ie the following code:

var handler = new Handler();
handler.AppendFormatted((dynamic)5);

ref struct Handler
{
    // or public void AppendFormatted<T>(T value) { }
    public void AppendFormatted(object value) { }
}

Will result in something like this generated by compiler :

private static class <>o__0
{
    public static CallSite<<>A{00000002}<CallSite, Handler, object>> <>p__0;
}

Note the Handler in the list of type parameters which will lead to the exactly the same runtime error. Removing ref from the handler fixes the issue.

As noted in comments in this test and this comment by Stephen Toub currently Roslyn does not emit any build time errors for this code while it fails in runtime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM