Description
I'm using System.Linq.Expressions
to implement formatters (serializers) for any type T.
At runtime everything works fine, but now I want to support IL2CPP (Unitys ahead-of-time compiler).
So I thought I'd just get a list of all types to be serialized in my serializer, and then compile those expressions using CompileToMethod
and then saving them in an assembly.
That way - for IL2CPP - no code has to be compiled at runtime.
The issue is that the constants in the expression tree can't be saved, which is no surprise.
Each formatter (expression tree) has can have 0-N sub formatters that it uses to serialize the individual fields of its type. For example: A formatter IFormatter<Person>
generated for class Person { public int Age; public string Name; }
would itself contain IFormatter<int>
and IFormatter<string>
in order to serialize the two fields.
Ok, so it's obvious to me why this doesn't work.
So my idea now is to somehow replace the constants (the sub formatters) in the expression trees with fields!
So instead of genrating the two expressions (serialize and deserialize) of the IFormatter<Person>
on their own, I would use DynamicType/TypeBuilder to generate a type that has fields for the needed formatters.
A Expression.Constant(stringFormatterInstance);
I would generate something like Expression.MakeMemberAccess(???, stringFormatterField)
.
Now my problem is, there's no Expression.This()
is there?
Also the LambdaCompiler seems to always want to include some sort of closure object. Maybe I can manually instantiate that somehow and use it as my "this"?
I'm a bit confused now regarding what my options are to actually solve this.
Maybe there's some other way to replace the constants when loading the generated assembly?
The solution obviously can't be anything that uses dynamic code generation, as the whole point is to have this run on an AOT platform.