Skip to content

Commit f3af0ce

Browse files
Added custom props attribute (#1868)
* Added custom props attribute * Updated the docs * Values must match
1 parent ec61745 commit f3af0ce

File tree

4 files changed

+129
-37
lines changed

4 files changed

+129
-37
lines changed

docs/usage.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,21 @@ request.AddParameter("ids", "123,456");
215215

216216
Remember that `AddObject` only works if your properties have primitive types. It also works with collections of primitive types as shown above.
217217

218+
If you need to override the property name or format, you can do it using the `RequestProperty` attribute. For example:
219+
220+
```csharp
221+
public class RequestModel {
222+
// override the name and the format
223+
[RequestAttribute(Name = "from_date", Format = "d")]
224+
public DateTime FromDate { get; set; }
225+
}
226+
227+
// add it to the request
228+
request.AddObject(new RequestModel { FromDate = DateTime.Now });
229+
```
230+
231+
In this case, the request will get a GET or POST parameter named `from_date` and its value would be the current date in short date format.
232+
218233
### Url Segment
219234

220235
Unlike `GetOrPost`, this `ParameterType` replaces placeholder values in the `RequestUrl`:

src/RestSharp/Extensions/MiscExtensions.cs renamed to src/RestSharp/Extensions/StreamExtensions.cs

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace RestSharp.Extensions;
1717
/// <summary>
1818
/// Extension method overload!
1919
/// </summary>
20-
static class MiscExtensions {
20+
static class StreamExtensions {
2121
/// <summary>
2222
/// Read a stream into a byte array
2323
/// </summary>
@@ -39,40 +39,4 @@ public static async Task<byte[]> ReadAsBytes(this Stream input, CancellationToke
3939

4040
return ms.ToArray();
4141
}
42-
43-
internal static IEnumerable<(string Name, string? Value)> GetProperties(this object obj, params string[] includedProperties) {
44-
// automatically create parameters from object props
45-
var type = obj.GetType();
46-
var props = type.GetProperties();
47-
48-
foreach (var prop in props) {
49-
if (!IsAllowedProperty(prop.Name))
50-
continue;
51-
52-
var val = prop.GetValue(obj, null);
53-
54-
if (val == null)
55-
continue;
56-
57-
var propType = prop.PropertyType;
58-
59-
if (propType.IsArray) {
60-
var elementType = propType.GetElementType();
61-
var array = (Array)val;
62-
63-
if (array.Length > 0 && elementType != null) {
64-
// convert the array to an array of strings
65-
var values = array.Cast<object>().Select(item => item.ToString());
66-
yield return (prop.Name, string.Join(",", values));
67-
68-
continue;
69-
}
70-
}
71-
72-
yield return (prop.Name, val.ToString());
73-
}
74-
75-
bool IsAllowedProperty(string propertyName)
76-
=> includedProperties.Length == 0 || includedProperties.Length > 0 && includedProperties.Contains(propertyName);
77-
}
7842
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright © 2009-2020 John Sheehan, Andrew Young, Alexey Zimarev and RestSharp community
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
//
15+
16+
using System.Reflection;
17+
18+
namespace RestSharp;
19+
20+
static class ObjectParser {
21+
public static IEnumerable<(string Name, string? Value)> GetProperties(this object obj, params string[] includedProperties) {
22+
// automatically create parameters from object props
23+
var type = obj.GetType();
24+
var props = type.GetProperties();
25+
26+
foreach (var prop in props.Where(x => IsAllowedProperty(x.Name))) {
27+
var val = prop.GetValue(obj, null);
28+
29+
if (val == null) continue;
30+
31+
yield return prop.PropertyType.IsArray
32+
? GetArray(prop, val)
33+
: GetValue(prop, val);
34+
}
35+
36+
string? ParseValue(string? format, object? value) => format == null ? value?.ToString() : string.Format($"{{0:{format}}}", value);
37+
38+
(string, string?) GetArray(PropertyInfo propertyInfo, object? value) {
39+
var elementType = propertyInfo.PropertyType.GetElementType();
40+
var array = (Array)value!;
41+
42+
var attribute = propertyInfo.GetCustomAttribute<RequestPropertyAttribute>();
43+
var name = attribute?.Name ?? propertyInfo.Name;
44+
45+
if (array.Length > 0 && elementType != null) {
46+
// convert the array to an array of strings
47+
var values = array
48+
.Cast<object>()
49+
.Select(item => ParseValue(attribute?.Format, item));
50+
return (name, string.Join(",", values));
51+
}
52+
53+
return (name, null);
54+
}
55+
56+
(string, string?) GetValue(PropertyInfo propertyInfo, object? value) {
57+
var attribute = propertyInfo.GetCustomAttribute<RequestPropertyAttribute>();
58+
var name = attribute?.Name ?? propertyInfo.Name;
59+
var val = ParseValue(attribute?.Format, value);
60+
return (name, val);
61+
}
62+
63+
bool IsAllowedProperty(string propertyName)
64+
=> includedProperties.Length == 0 || includedProperties.Length > 0 && includedProperties.Contains(propertyName);
65+
}
66+
}
67+
68+
[AttributeUsage(AttributeTargets.Property)]
69+
public class RequestPropertyAttribute : Attribute {
70+
public string? Name { get; set; }
71+
72+
public string? Format { get; set; }
73+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Globalization;
2+
3+
namespace RestSharp.Tests;
4+
5+
public class ObjectParserTests {
6+
[Fact]
7+
public void ShouldUseRequestProperty() {
8+
var now = DateTime.Now;
9+
var dates = new[] { now, now.AddDays(1), now.AddDays(2) };
10+
var request = new TestObject {
11+
SomeData = "test",
12+
SomeDate = now,
13+
Plain = 123,
14+
PlainArray = dates,
15+
DatesArray = dates
16+
};
17+
18+
var parsed = request.GetProperties().ToDictionary(x => x.Name, x => x.Value);
19+
parsed["some_data"].Should().Be(request.SomeData);
20+
parsed["SomeDate"].Should().Be(request.SomeDate.ToString("d"));
21+
parsed["Plain"].Should().Be(request.Plain.ToString());
22+
// ReSharper disable once SpecifyACultureInStringConversionExplicitly
23+
parsed["PlainArray"].Should().Be(string.Join(",", dates.Select(x => x.ToString())));
24+
parsed["dates"].Should().Be(string.Join(",", dates.Select(x => x.ToString("d"))));
25+
}
26+
27+
class TestObject {
28+
[RequestProperty(Name = "some_data")]
29+
public string SomeData { get; set; }
30+
31+
[RequestProperty(Format = "d")]
32+
public DateTime SomeDate { get; set; }
33+
34+
[RequestProperty(Name = "dates", Format = "d")]
35+
public DateTime[] DatesArray { get; set; }
36+
37+
public int Plain { get; set; }
38+
public DateTime[] PlainArray { get; set; }
39+
}
40+
}

0 commit comments

Comments
 (0)