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

Add tests for struct access #706

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Fluid.Tests/Domain/Person.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }

public Colors EyesColor { get; set; }
public Address Address { get; set; }
}

Expand All @@ -13,4 +13,11 @@ public class Address
public string City { get; set; }
public string State { get; set; }
}

public enum Colors
{
Blue,
Red,
Yellow
}
}
9 changes: 9 additions & 0 deletions Fluid.Tests/Domain/Shape.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Drawing;

namespace Fluid.Tests.Domain
{
public class Shape
{
public Point Coordinates { get; set; }
}
}
34 changes: 34 additions & 0 deletions Fluid.Tests/MemberAccessStrategyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
using Fluid.Tests.Domain;
using Fluid.Values;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Threading.Tasks;
using Xunit;

Expand Down Expand Up @@ -239,6 +241,38 @@ public void ShouldUseDictionaryAsModel()

Assert.Equal("Bill Gates", template.Render(new TemplateContext(model, options)));
}

[Fact]
public void ShouldResolveEnums()
{
var options = new TemplateOptions();
options.MemberAccessStrategy.Register<Person>();

var john = new Person { Firstname = "John", EyesColor = Colors.Yellow };

var template = _parser.Parse("{{Firstname}} {{EyesColor}}");
Assert.Equal("John 2", template.Render(new TemplateContext(john, options, false)));
}

[Fact]
public void ShouldResolveStructs()
{
// We can't create an open delegate on a Struc (dotnet limitation?), so instead create custom delegates
// https://sharplab.io/#v2:EYLgtghglgdgNAFxAJwK7wCYgNQB8ACATAAwCwAUEQIwX7EAE+VAdACLIQDusA5gNwUKANwjJ6ABwCSMAGYB7egF56CAJ7iApnJkAKAApzYCAJTMA4hoR7kczcjU6ARAA1HxgeRFiMhJROny5pYWCACylgAWchg6pgDCyBoQCBqsGgA2GjzJGjpqmto6+ACsADwGRnD0RgB8xu4UQA==

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)));
}
}

public class Class1
Expand Down
14 changes: 11 additions & 3 deletions Fluid/MemberAccessStrategyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,35 @@ internal static Dictionary<string, IMemberAccessor> GetTypeMembers(Type type, Me
}

if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Task<>))
{
list[memberNameStrategy(propertyInfo)] = new AsyncDelegateAccessor(async (o, n) =>
{
var asyncValue = (Task)propertyInfo.GetValue(o);
await asyncValue.ConfigureAwait(false);
return (object)((dynamic)asyncValue).Result;
});
}
else
{
list[memberNameStrategy(propertyInfo)] = new PropertyInfoAccessor(propertyInfo);
}
}

foreach (var fieldInfo in key.Type.GetTypeInfo().GetFields(BindingFlags.Public | BindingFlags.Instance))
{
if (fieldInfo.FieldType.IsGenericType && fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(Task<>))
{
list[memberNameStrategy(fieldInfo)] = new AsyncDelegateAccessor(async (o, n) =>
{
var asyncValue = (Task)fieldInfo.GetValue(o);
await asyncValue.ConfigureAwait(false);
return (object)((dynamic)asyncValue).Result;
});
}
else
{
list[memberNameStrategy(fieldInfo)] = new DelegateAccessor((o, n) => fieldInfo.GetValue(o));
}
}

return list;
Expand All @@ -76,7 +84,7 @@ internal static IMemberAccessor GetNamedAccessor(Type type, string name, MemberN
/// </summary>
/// <typeparam name="T">The type to register.</typeparam>
/// <param name="strategy">The <see cref="MemberAccessStrategy"/>.</param>
public static void Register<T>(this MemberAccessStrategy strategy) where T : class
public static void Register<T>(this MemberAccessStrategy strategy)
{
Register(strategy, typeof(T));
}
Expand All @@ -97,7 +105,7 @@ public static void Register(this MemberAccessStrategy strategy, Type type)
/// <typeparam name="T">The type to register.</typeparam>
/// <param name="strategy">The <see cref="MemberAccessStrategy"/>.</param>
/// <param name="names">The names of the properties in the type to register.</param>
public static void Register<T>(this MemberAccessStrategy strategy, params string[] names) where T : class
public static void Register<T>(this MemberAccessStrategy strategy, params string[] names)
{
strategy.Register(typeof(T), names);
}
Expand All @@ -108,7 +116,7 @@ public static void Register<T>(this MemberAccessStrategy strategy, params string
/// <typeparam name="T">The type to register.</typeparam>
/// <param name="strategy">The <see cref="MemberAccessStrategy"/>.</param>
/// <param name="names">The property's expressions in the type to register.</param>
public static void Register<T>(this MemberAccessStrategy strategy, params Expression<Func<T, object>>[] names) where T : class
public static void Register<T>(this MemberAccessStrategy strategy, params Expression<Func<T, object>>[] names)
{
strategy.Register<T>(names.Select(ExpressionHelper.GetPropertyName).ToArray());
}
Expand Down