Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AOT support when using AddSubType #318

Open
rodrigovaras opened this issue Nov 29, 2023 · 4 comments
Open

AOT support when using AddSubType #318

rodrigovaras opened this issue Nov 29, 2023 · 4 comments

Comments

@rodrigovaras
Copy link

I understand there is an upcoming work to fully support AOT but in the meantime i was looking on a way to include the assemblies for the reflection support on the AOT bundle.

I'm not able to go further when my code hits this:
static RpcContextExtensions()
{
RuntimeTypeModel.Default[typeof(ActionConfiguration)]
.AddSubType(100, typeof(ActionBindingConfiguration))
.AddSubType(101, typeof(ActionExpressionConfiguration));
}

When running my AOT app it shows this:
System.TypeInitializationException: A type initializer threw an exception. To determine which type, inspect the InnerException's StackTrace property.
---> System.ArgumentException: Value does not fall within the expected range.
at System.Reflection.Runtime.PropertyInfos.RuntimePropertyInfo.GetValue(Object, BindingFlags, Binder, Object[], CultureInfo) + 0xbb
at System.Reflection.PropertyInfo.GetValue(Object, Object[]) + 0x1d
at ProtoBuf.Meta.AttributeMap.ReflectionAttributeMap.TryGet(String, Boolean, Object&) + 0xa8
at ProtoBuf.Meta.MetaType.GetFieldNumber(Int32&, AttributeMap, String) + 0x39
at ProtoBuf.Meta.MetaType.NormalizeProtoMember(MemberInfo, MetaType.AttributeFamily, Boolean, Boolean, List1, Int32, Boolean, EnumMember&, MemberInfo) + 0x59c at ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour_AddMembers(MetaType.AttributeFamily, Boolean, List1, Int32, Boolean, ImplicitFields, List1, MemberInfo, Boolean&, Boolean, Boolean, Type&, List1, MemberInfo) + 0xd8
at ProtoBuf.Meta.MetaType.ApplyDefaultBehaviourImpl(CompatibilityLevel) + 0xea0
at ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour(CompatibilityLevel) + 0x3c
at ProtoBuf.Meta.RuntimeTypeModel.FindOrAddAuto(Type, Boolean, Boolean, Boolean, CompatibilityLevel) + 0x1ed
at ProtoBuf.Meta.RuntimeTypeModel.get_Item(Type) + 0x28
at ProtoBuf.Meta.MetaType.AddSubType(Int32, Type, DataFormat) + 0xb4
at Teksoft.Node.Rpc.RpcContextExtensions..cctor() + 0x4e

Any way to avoid this? By using the [ProtoInclude] will this still happen ?
BTW, i was trying to avoid using the [ProtoInclude] since i did not want my contract assembly to depend on protobuff-Core hence i did it by code when needed.

@mgravell
Copy link
Member

We do not claim AOT support currently; I do not know, without checking, which hurdle this is hitting, so it is hard for me to comment on what would work and what wouldn't

@rodrigovaras
Copy link
Author

I did investigate further this and get into the bottom of the problem.
A basic HelloModel will fail under AOT.
It seems that the failure i was pointing is the fact that the protobuf lib is attempting to fully reflect the DataMemeber or ProtoMember attributes and hence failing when AOT trimm all the reflection daata on those classes.

Adding this on the rd.xml in your AOT host app will make this erro go away:





    <Assembly Name ="System.Runtime.Serialization.Primitives">
        <Type Name="System.Runtime.Serialization.DataContractAttribute" Dynamic="Required All" />
        <Type Name="System.Runtime.Serialization.DataMemberAttribute" Dynamic="Required All" />
    </Assembly>

But there is another more challenge problem, when using for example:
public class Foo
{
public Bar Bar {get;set;}
}

The inner class make protobuf fail here:
Unhandled Exception: System.InvalidOperationException: No serializer defined for type: Bar
at ProtoBuf.Internal.ThrowHelper.NoSerializerDefined(Type) + 0xe1
at ProtoBuf.Meta.ValueMember.BuildSerializer() + 0x1c5
at ProtoBuf.Meta.ValueMember.get_Serializer() + 0x1a
at ProtoBuf.Meta.MetaType.BuildSerializer() + 0x6a7

I suspect the problem could be the usage of MakeGenericType() inside protobuf lib.

@mgravell
Copy link
Member

mgravell commented Dec 2, 2023

Yes, that's entirely likely. We make zero claims of AOT compat. I know what is involved in bridging this gap, and it isn't trivial. It is on the roadmap, but I cannot offer you that today.

@rodrigovaras
Copy link
Author

I look further on what AOT was doing with the trimming and found the proper generic construction that was throwing is here:
try
{
return (DynamicStub)Activator.CreateInstance(typeDef.MakeGenericType(args), nonPublic: true); <===
}
catch (Exception e)
{
return NilStub.Instance;
}

The silent error was hard to track and find the exact spot where AOT was failing.
Good news is that there is a mitigation by properly configuring the rd.xml file when running the AOT tools.
I did this and it worked:

    <Assembly Name ="protobuf-net.Core">
		<Type Name="ProtoBuf.Internal.DynamicStub+ConcreteStub`1[[ConsoleApp4.Error, ConsoleApp4]]" Dynamic="Required All" />

The 'Error' type was inside my 'Address' type class under a simple 'ConsoleApp4' assembly and namespace.

This workaround would work until the library change the names but at least i think it will unblock me from more testing AOT.

Thanks for your quick responses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants