orleans icon indicating copy to clipboard operation
orleans copied to clipboard

Add support for `dynamic` members

Open ReubenBond opened this issue 3 years ago • 8 comments

Currently, the following type definition, which has a dynamic member, causes the code generator to fail:

[GenerateSerializer]
public class TelemetryMessageValue
{
    [Id(0)]
    public string Name { get; set; }
    [Id(1)]
    public DateTimeOffset Timestamp { get; set; }
    [Id(2)]
    public dynamic Value { get; set; }

    public TelemetryMessageValue(string name, dynamic value, DateTimeOffset? timestamp = null)
    {
        this.Name = name;
        this.Value = value;
        this.Timestamp = timestamp ?? DateTimeOffset.Now;
    }
}

We should treat dynamic similarly to object.

ReubenBond avatar Feb 18 '22 00:02 ReubenBond

I am happy to look at this over the weekend.

jeremylcarter avatar Jul 15 '22 03:07 jeremylcarter

That would be greatly appreciated! Feel free to message me (eg on discord) if you have any questions

ReubenBond avatar Jul 15 '22 03:07 ReubenBond

Ok so I have had a deep dive and here's what I've found.

The existing code looks for dynamic by checking Type.TypeKind == TypeKind.Dynamic. This evaluates to true which is correct, problem is the symbol type is actually IDynamicTypeSymbol which isnt factored in with the switch inside the extension method GetValidIdentifier(). Once you factor that in and assume that all dynamics can be treated as objects then we can move on. The next problem is that the IDynamicTypeSymbol gets in the way further on down the chain so I have replaced it with (ITypeSymbol)typeof(object) just to get things moving but this feels wrong. I'm still figuring out how it works 👍

if (Type.TypeKind == TypeKind.Dynamic)
{
    Type = (ITypeSymbol)typeof(object);
    TypeSyntax = PredefinedType(Token(SyntaxKind.ObjectKeyword));
}
public static string GetValidIdentifier(this ITypeSymbol type) => type switch
{
    IDynamicTypeSymbol dynamic => "Object",
    INamedTypeSymbol named when !named.IsGenericType => $"{named.Name}",
    INamedTypeSymbol named => $"{named.Name}_{string.Join("_", named.TypeArguments.Select(GetValidIdentifier))}",
    IArrayTypeSymbol array => $"{GetValidIdentifier(array.ElementType)}_{array.Rank}",
    ITypeParameterSymbol parameter => $"{parameter.Name}",
    _ => throw new NotSupportedException($"Unable to format type of kind {type.GetType()} with name \"{type.Name}\""),
};

jeremylcarter avatar Jul 16 '22 04:07 jeremylcarter

Hi,

Has there been any update on this, as we are trying to migrate to Orleans 7.2.1 and we have a dynamic property in a class sent to a grain but we get the error below when code is generated:

CS1978 Cannot use an expression of type 'Writer<TBufferWriter>' as an argument to a dynamically dispatched operation.

Is there a workaround for the time being?

Thanks

sjbthfc2 avatar Jul 20 '23 08:07 sjbthfc2

@sjbthfc2 can you use object instead of dynamic? What is the type being stored in the dynamic member?

ReubenBond avatar Jul 20 '23 14:07 ReubenBond

Hi,

Yes we have switched to using object for now as a workaround. Will dynamic be supported in the future?

sjbthfc2 avatar Jul 21 '23 08:07 sjbthfc2

Any update on this? We're doing a migration from 3.x to 8.x and ran into this same issue. Changing to object is feasible, but has ripple effects through our codebase.

cbgrasshopper avatar Apr 10 '24 10:04 cbgrasshopper