How to use System.Text.Json.JsonSerializer.Serialize in Metalama

751 views Asked by At

I am trying to convert an object to json represented string using System.Text.Json.JsonSerializer.Serialize function in Metalama OverrideMethodAspect in my Logger class like this:

public class LoggObjectAttribute : OverrideMethodAspect
{
    public LoggObjectAttribute()
    {
    }

    public override dynamic OverrideMethod()
    {
        // Build a formatting string.
        var methodName = BuildInterpolatedString();
        var user = meta.ParseExpression("this._httpContextAccessor?.HttpContext?.User?.Identity?.Name");

        // Write entry message.
        var entryMessage = methodName.Clone();

        entryMessage.AddText(" started by user: ");
        entryMessage.AddExpression(user?.Value);

        meta.This._logger.LogInformation(entryMessage.ToValue());

        try
        {
            // Invoke the method.
            var result = meta.Proceed();

            // Display the success message.
            var successMessage = methodName.Clone();

            if (meta.Target.Method.ReturnType.Is(typeof(void)))
            {
                successMessage.AddText(" succeeded.");
            }
            else
            {
                successMessage.AddText(" => ");
                successMessage.AddExpression(result);
            }

            meta.This._logger.LogInformation(successMessage.ToValue());

            return result;
        }
        catch (Exception e)
        {
            // Display the failure message.
            var failureMessage = methodName.Clone();
            failureMessage.AddText(" failed: ");
            failureMessage.AddExpression(e.Message);
            meta.This._logger.LogInformation(failureMessage.ToValue());

            throw;
        }
    }

    protected InterpolatedStringBuilder BuildInterpolatedString()
    {
        var stringBuilder = new InterpolatedStringBuilder();

        stringBuilder.AddText(meta.Target.Method.Name);

        stringBuilder.AddText("(");

        var i = meta.CompileTime(0);

        foreach (var prop in meta.Target.Parameters)
        {
            var comma = i > 0 ? ", " : "";

            if (prop.RefKind == RefKind.Out)
            {
                stringBuilder.AddText($"{comma}{prop.Name} = <out> ");
            }
            else
            {
                
                stringBuilder.AddText(prop.Name);
                stringBuilder.AddText(" : ");
                string json = JsonSerializer.Serialize(prop.Value);
                stringBuilder.AddText(json);
                //stringBuilder.AddExpression(prop.Value);
            }

            i++;
        }

        stringBuilder.AddText(")");

        return stringBuilder;
    }
}

When I tried to compile the code I got this error: error CS0234: The type or namespace name 'Json' does not exist in the namespace 'System.Text' (are you missing an assembly reference?)

In my gloabl import I have reference on System.Text and System.Text.Json. The same applies to the global imports in the project where I have my controllers (this is a .net 6 rest api project, where the Logger class is in another class library project). The code is generated in compile time.

To find an error I found out that Metalama on code generating does not import the System.Text.Json namespace only the System.Text. This might be a problem?! Is this a bug, or I am doing something wrong?

thnx

1

There are 1 answers

0
Gael Fraiteur On

As documented, you need to add the Newtonsoft.Json package to the list of compile-time packages:

<ItemGroup>
 <MetalamaCompileTimePackage Include="Newtonsoft.Json"/>
</ItemGroup>