fluid icon indicating copy to clipboard operation
fluid copied to clipboard

Supporting `struct` by default, would be great

Open schittli opened this issue 2 years ago • 1 comments

Good evening

thanks a lot for sharing your great work!

I tried to use fluid with c# struct objects and it looks like fluid usually always expects to get class objects, for example, TemplateOptions.Default.MemberAccessStrategy.Register<T> is declared with: where T : class

I guess, that it would be great if fluid would support structs, by default, too.

Thanks a lot, kind regards, Thomas

schittli avatar Feb 20 '23 20:02 schittli

using a struct anywhere will throw System.ArgumentException Cannot bind to the target method because its signature is not compatible with that of the delegate type

System.ArgumentException Cannot bind to the target method because its signature is not compatible with that of the delegate type.
   at System.Reflection.RuntimeMethodInfo.CreateDelegateInternal(Type delegateType, Object firstArgument, DelegateBindingFlags bindingFlags)
   at Fluid.Accessors.PropertyInfoAccessor..ctor(PropertyInfo propertyInfo)
   at Fluid.MemberAccessStrategyExtensions.<>c__DisplayClass1_0.<GetTypeMembers>b__0(ValueTuple`2 key)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
   at Fluid.MemberAccessStrategyExtensions.GetTypeMembers(Type type, MemberNameStrategy memberNameStrategy)
   at Fluid.MemberAccessStrategyExtensions.Register(MemberAccessStrategy strategy, Type type)
   at Fluid.UnsafeMemberAccessStrategy.GetAccessor(Type type, String name)
   at Fluid.Values.ObjectValueBase.GetValueAsync(String name, TemplateContext context)
   at Fluid.Ast.IdentifierSegment.ResolveAsync(FluidValue value, TemplateContext context)
   at Fluid.Ast.MemberExpression.EvaluateAsync(TemplateContext context)
   at Fluid.Ast.OutputStatement.WriteToAsync(TextWriter writer, TextEncoder encoder, TemplateContext context)
   at Fluid.Parser.FluidTemplate.RenderAsync(TextWriter writer, TextEncoder encoder, TemplateContext context)
   at Fluid.FluidTemplateExtensions.RenderAsync(IFluidTemplate template, TemplateContext context, TextEncoder encoder, Boolean isolateContext)

mhehle avatar Aug 13 '24 13:08 mhehle

What is the workaround here? I want to use units from the UnitsNet library and those are all structs.

Brunni avatar Oct 23 '24 15:10 Brunni

I found a workaround, here is an example with Point which is a struct:

            var options = new TemplateOptions();
            options.MemberAccessStrategy.Register<Shape>();
            options.MemberAccessStrategy.Register<Point>(nameof(Point.X), new DelegateAccessor<Point, int>((point, name, context) => point.X));
            options.MemberAccessStrategy.Register<Point>(nameof(Point.Y), new DelegateAccessor<Point, int>((point, name, context) => point.Y));

            var circle = new Shape
            {
                Coordinates = new Point(1, 2)
            };

            var template = _parser.Parse("{{Coordinates.X}} {{Coordinates.Y}}");
            Assert.Equal("1 2", template.Render(new TemplateContext(circle, options, false)));

sebastienros avatar Oct 23 '24 16:10 sebastienros