Skip to content

Commit

Permalink
Merge pull request #117 from pikami/feature/Custom-Property-Name
Browse files Browse the repository at this point in the history
Implemented 'ODataPropertyName' attribute
  • Loading branch information
ZEXSM authored May 18, 2024
2 parents 682194b + d536c72 commit e3549b9
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 38 deletions.
15 changes: 15 additions & 0 deletions src/OData.QueryBuilder/Attributes/ODataPropertyNameAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace OData.QueryBuilder.Attributes
{
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
public class ODataPropertyNameAttribute : Attribute

Check warning on line 6 in src/OData.QueryBuilder/Attributes/ODataPropertyNameAttribute.cs

View workflow job for this annotation

GitHub Actions / build&test&coverage(ubuntu-latest)

Missing XML comment for publicly visible type or member 'ODataPropertyNameAttribute'
{
public string Name;

Check warning on line 8 in src/OData.QueryBuilder/Attributes/ODataPropertyNameAttribute.cs

View workflow job for this annotation

GitHub Actions / build&test&coverage(ubuntu-latest)

Missing XML comment for publicly visible type or member 'ODataPropertyNameAttribute.Name'

public ODataPropertyNameAttribute(string name)
{
Name = name;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using OData.QueryBuilder.Extensions;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
using OData.QueryBuilder.Attributes;

namespace OData.QueryBuilder.Expressions.Visitors
{
Expand Down Expand Up @@ -53,7 +55,7 @@ protected virtual string VisitMethodCallExpression(LambdaExpression topExpressio
if (genericMethodType != memberExpression.Type)
throw new ArgumentException(
$"The type '{genericMethodType.FullName}' specified when calling 'ODataProperty.FromPath<T>(\"{propertyPath}\")' does not match the expected type '{memberExpression.Type.FullName}' defined by the model.");

return VisitMemberExpression(topExpression, memberExpression);
}
}
Expand All @@ -78,15 +80,22 @@ protected virtual string VisitMemberExpression(LambdaExpression topExpression, M
{
var memberName = VisitExpression(topExpression, memberExpression.Expression);

var reflectedMemberName = memberExpression.Member.Name;
var propertyNameAttribute = memberExpression.Member.GetCustomAttribute<ODataPropertyNameAttribute>();
if (propertyNameAttribute != null)
{
reflectedMemberName = propertyNameAttribute.Name;
}

if (string.IsNullOrEmpty(memberName))
{
return memberExpression.Member.Name;
return reflectedMemberName;
}

return memberExpression.Member.DeclaringType.IsNullableType() ?
memberName
:
$"{memberName}/{memberExpression.Member.Name}";
$"{memberName}/{reflectedMemberName}";
}

public virtual string ToQuery(LambdaExpression expression) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
<TargetFramework>netstandard2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
</Project>

<ItemGroup>
<ProjectReference Include="..\..\src\OData.QueryBuilder\OData.QueryBuilder.csproj" />
</ItemGroup>
</Project>
4 changes: 4 additions & 0 deletions test/OData.QueryBuilder.Fakes/ODataKindEntity.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using OData.QueryBuilder.Attributes;

namespace OData.QueryBuilder.Fakes
{
Expand All @@ -23,5 +24,8 @@ public class ODataKindEntity
public long[] SequenceLongArray { get; set; }

public ColorEnum Color { get; set; }

[ODataPropertyName("customName")]
public string CustomNamedProperty { get; set; }
}
}
70 changes: 36 additions & 34 deletions test/OData.QueryBuilder.Test/ODataQueryCollectionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public void ODataQueryBuilderList_Expand_DynamicProperty_Success()
.ToUri();

uri.Should().Be("http://mock/odata/ODataType?$expand=ODataKind");
}

}

[Fact(DisplayName = "Select simple => Success")]
public void ODataQueryBuilderList_Select_Simple_Success()
{
Expand All @@ -69,8 +69,8 @@ public void ODataQueryBuilderList_Select_DynamicProperty_Success()
.ToUri();

uri.Should().Be("http://mock/odata/ODataType?$select=IdType");
}

}

[Fact(DisplayName = "OrderBy simple => Success")]
public void ODataQueryBuilderList_OrderBy_Simple_Success()
{
Expand All @@ -93,8 +93,8 @@ public void ODataQueryBuilderList_OrderBy_DynamicProperty_Success()
.ToUri();

uri.Should().Be("http://mock/odata/ODataType?$orderby=IdType asc");
}

}

[Fact(DisplayName = "Filter orderBy multiple sort => Success")]
public void ODataQueryBuilderList_Filter_OrderBy_Multiple_Sort_Success()
{
Expand Down Expand Up @@ -354,8 +354,8 @@ public void ODataQueryBuilderList_Filter_With_ReplaceCharacters_KeyValuePairs_Ar
[Fact(DisplayName = "Filter variable dynamic property int=> Success")]
public void ODataQueryBuilderList_Filter_Simple_Variable_DynamicProperty_Success()
{
string propertyName = "ODataKind.ODataCode.IdCode";

string propertyName = "ODataKind.ODataCode.IdCode";

var uri = _odataQueryBuilderDefault
.For<ODataTypeEntity>(s => s.ODataType)
.ByList()
Expand All @@ -376,8 +376,8 @@ public void ODataQueryBuilderList_Filter_Simple_Variable_DynamicProperty_WrongTy
.ByList()
.Filter((s, f, _) => ODataProperty.FromPath<string>(propertyName) == "test")
.ToUri()).Should().Throw<ArgumentException>();
}

}

[Fact(DisplayName = "Filter const dynamic property int=> Success")]
public void ODataQueryBuilderList_Filter_Simple_Const_DynamicProperty_Success()
{
Expand All @@ -388,8 +388,8 @@ public void ODataQueryBuilderList_Filter_Simple_Const_DynamicProperty_Success()
.ToUri();

uri.Should().Be("http://mock/odata/ODataType?$filter=ODataKind/ODataCode/IdCode ge 3");
}

}

[Fact(DisplayName = "Filter simple const int=> Success")]
public void ODataQueryBuilderList_Filter_Simple_Const_Int_Success()
{
Expand Down Expand Up @@ -576,6 +576,7 @@ public void ODataQueryBuilderList_Function_Date_Success()
&& s.ODataKind.OpenDate == currentDateToday
&& s.ODataKind.OpenDate == DateTime.Today
&& s.ODataKind.OpenDate == new DateTimeOffset()
&& s.ODataKind.CustomNamedProperty == "test"
&& s.Open == new DateTime()
&& f.Date(s.Open) == DateTime.Today
&& f.Date(s.Open) == DateTimeOffset.Now
Expand All @@ -592,6 +593,7 @@ public void ODataQueryBuilderList_Function_Date_Success()
$"and ODataKind/OpenDate eq 2019-02-09T00:00:00Z " +
$"and ODataKind/OpenDate eq {DateTime.Today:s}Z " +
$"and ODataKind/OpenDate eq {new DateTimeOffset():s}Z " +
$"and ODataKind/customName eq 'test' " +
$"and Open eq {new DateTime():s}Z " +
$"and date(Open) eq {DateTime.Today:s}Z " +
$"and date(Open) eq {DateTimeOffset.Now:s}Z " +
Expand Down Expand Up @@ -1560,39 +1562,39 @@ public void ODataQueryBuilder_Function_Cast_Skip_Exception(string value)
.ToUri();

uri.Should().Be("http://mock/odata/ODataType?$filter=contains(,'55')");
}

}

[Fact(DisplayName = "UseCorrectDateTimeFormat Convert => Success")]
public void ODataQueryBuilderList_UseCorrectDatetimeFormat_Convert_Success()
{
var builder = new ODataQueryBuilder<ODataInfoContainer>(
_commonFixture.BaseUri,
new ODataQueryBuilderOptions { UseCorrectDateTimeFormat = true });

var dateTimeLocal = new DateTime(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, kind: DateTimeKind.Local);
var dateTimeUtc = new DateTime(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, kind: DateTimeKind.Utc);
var dateTimeOffset = new DateTimeOffset(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, offset: TimeSpan.FromHours(+7));
var dateTimeOffset2 = new DateTimeOffset(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, offset: TimeSpan.FromHours(-7));
{
var builder = new ODataQueryBuilder<ODataInfoContainer>(
_commonFixture.BaseUri,
new ODataQueryBuilderOptions { UseCorrectDateTimeFormat = true });

var dateTimeLocal = new DateTime(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, kind: DateTimeKind.Local);
var dateTimeUtc = new DateTime(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, kind: DateTimeKind.Utc);
var dateTimeOffset = new DateTimeOffset(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, offset: TimeSpan.FromHours(+7));
var dateTimeOffset2 = new DateTimeOffset(
year: 2023, month: 04, day: 07, hour: 12, minute: 30, second: 20, offset: TimeSpan.FromHours(-7));
var nowOffset = $"{DateTimeOffset.Now:zzz}".Replace("+", "%2B");

var uri = builder
.For<ODataTypeEntity>(s => s.ODataType)
.ByList()
.Filter((o) =>
o.DateTime == dateTimeLocal
&& o.DateTime == dateTimeUtc
&& o.DateTime == dateTimeOffset
.Filter((o) =>
o.DateTime == dateTimeLocal
&& o.DateTime == dateTimeUtc
&& o.DateTime == dateTimeOffset
&& o.DateTime == dateTimeOffset2)
.ToUri();

uri.Should().Be($"http://mock/odata/ODataType?$filter=" +
$"DateTime eq 2023-04-07T12:30:20{nowOffset} and " +
$"DateTime eq 2023-04-07T12:30:20%2B00:00 and " +
$"DateTime eq 2023-04-07T12:30:20%2B07:00 and " +
$"DateTime eq 2023-04-07T12:30:20{nowOffset} and " +
$"DateTime eq 2023-04-07T12:30:20%2B00:00 and " +
$"DateTime eq 2023-04-07T12:30:20%2B07:00 and " +
$"DateTime eq 2023-04-07T12:30:20-07:00");
}
}
Expand Down

0 comments on commit e3549b9

Please sign in to comment.