Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 4f780f9

Browse files
authored
prepare 3.6.0 (#65)
1 parent c9a3923 commit 4f780f9

File tree

10 files changed

+805
-377
lines changed

10 files changed

+805
-377
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
All notable changes to the LaunchDarkly .NET SDK will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org).
44

5+
## [3.6.0] - 2018-02-19
6+
### Added
7+
- New property `LdClient.Version` returns the client's current version number.
8+
- Adds support for a future LaunchDarkly feature, coming soon: semantic version user attributes.
9+
- Custom attributes can now have long integer values.
10+
11+
### Changed
12+
- It is now possible to compute rollouts based on an integer attribute of a user, not just a string attribute.
13+
514
## [3.5.0] - 2018-01-29
615
### Added
716
- Support for specifying [private user attributes](https://docs.launchdarkly.com/docs/private-user-attributes) in order to prevent user attributes from being sent in analytics events back to LaunchDarkly. See the `AllAttributesPrivate` and `PrivateAttributeNames` methods on `Configuration` as well as the `AndPrivateX` methods on `User`.

src/LaunchDarkly.Client/ILdClient.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ public interface ILdClient
1919
IDictionary<string, JToken> AllFlags(User user);
2020
string SecureModeHash(User user);
2121

22+
/// <summary>
23+
/// Returns the current version number of the LaunchDarkly client.
24+
/// </summary>
25+
Version Version { get; }
26+
2227
[Obsolete("Please use BoolVariation instead.")]
2328
bool Toggle(string key, User user, bool defaultValue = false);
2429
}

src/LaunchDarkly.Client/LaunchDarkly.Client.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<VersionPrefix>3.5.0</VersionPrefix>
3+
<VersionPrefix>3.6.0</VersionPrefix>
44
<TargetFrameworks>netstandard1.4;netstandard1.6;netstandard2.0;net45</TargetFrameworks>
55
<PackageLicenseUrl>https://raw.githubusercontent.com/launchdarkly/.net-client/master/LICENSE</PackageLicenseUrl>
66
<DebugType>portable</DebugType>

src/LaunchDarkly.Client/LdClient.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Reflection;
34
using System.Security.Cryptography;
45
using Microsoft.Extensions.Logging;
56
using Newtonsoft.Json.Linq;
@@ -240,6 +241,14 @@ public void Identify(User user)
240241
_eventStore.Add(new IdentifyEvent(EventUser.FromUser(user, _configuration), user));
241242
}
242243

244+
public Version Version
245+
{
246+
get
247+
{
248+
return typeof(LdClient).GetTypeInfo().Assembly.GetName().Version;
249+
}
250+
}
251+
243252
private void sendFlagRequestEvent(string key, User user, JToken value, JToken defaultValue, JToken version)
244253
{
245254
_eventStore.Add(new FeatureRequestEvent(key, EventUser.FromUser(user, _configuration), user, value, defaultValue, version, null));

src/LaunchDarkly.Client/Operator.cs

Lines changed: 65 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@ public static bool Apply(string op, JValue uValue, JValue cValue)
1515
{
1616
if (uValue == null || cValue == null)
1717
return false;
18-
19-
double? uDouble;
20-
DateTime? uDateTime;
18+
2119
switch (op)
2220
{
2321
case "in":
@@ -31,117 +29,34 @@ public static bool Apply(string op, JValue uValue, JValue cValue)
3129
return uValue.Value<string>().Equals(cValue.Value<string>());
3230
}
3331

34-
uDouble = ParseDoubleFromJValue(uValue);
35-
if (uDouble.HasValue)
36-
{
37-
var cDouble = ParseDoubleFromJValue(cValue);
38-
{
39-
if (cDouble.HasValue)
40-
{
41-
if (uDouble.Value.Equals(cDouble.Value)) return true;
42-
}
43-
}
44-
}
45-
break;
32+
return NumericOperator(uValue, cValue, (a, b) => a == b);
33+
4634
case "endsWith":
47-
if (uValue.Type.Equals(JTokenType.String) && cValue.Type.Equals(JTokenType.String))
48-
{
49-
return uValue.Value<string>().EndsWith(cValue.Value<string>());
50-
}
51-
break;
35+
return StringOperator(uValue, cValue, (a, b) => a.EndsWith(b));
5236
case "startsWith":
53-
if (uValue.Type.Equals(JTokenType.String) && cValue.Type.Equals(JTokenType.String))
54-
{
55-
return uValue.Value<string>().StartsWith(cValue.Value<string>());
56-
}
57-
break;
37+
return StringOperator(uValue, cValue, (a, b) => a.StartsWith(b));
5838
case "matches":
59-
if (uValue.Type.Equals(JTokenType.String) && cValue.Type.Equals(JTokenType.String))
60-
{
61-
var regex = new Regex(cValue.Value<string>());
62-
return regex.IsMatch(uValue.Value<string>());
63-
}
64-
break;
39+
return StringOperator(uValue, cValue, (a, b) => new Regex(b).IsMatch(a));
6540
case "contains":
66-
if (uValue.Type.Equals(JTokenType.String) && cValue.Type.Equals(JTokenType.String))
67-
{
68-
return uValue.Value<string>().Contains(cValue.Value<string>());
69-
}
70-
break;
41+
return StringOperator(uValue, cValue, (a, b) => a.Contains(b));
7142
case "lessThan":
72-
uDouble = ParseDoubleFromJValue(uValue);
73-
if (uDouble.HasValue)
74-
{
75-
var cDouble = ParseDoubleFromJValue(cValue);
76-
{
77-
if (cDouble.HasValue)
78-
{
79-
if (uDouble.Value < cDouble.Value) return true;
80-
}
81-
}
82-
}
83-
break;
43+
return NumericOperator(uValue, cValue, (a, b) => a < b);
8444
case "lessThanOrEqual":
85-
uDouble = ParseDoubleFromJValue(uValue);
86-
if (uDouble.HasValue)
87-
{
88-
var cDouble = ParseDoubleFromJValue(cValue);
89-
{
90-
if (cDouble.HasValue)
91-
{
92-
if (uDouble.Value <= cDouble.Value) return true;
93-
}
94-
}
95-
}
96-
break;
45+
return NumericOperator(uValue, cValue, (a, b) => a <= b);
9746
case "greaterThan":
98-
uDouble = ParseDoubleFromJValue(uValue);
99-
if (uDouble.HasValue)
100-
{
101-
var cDouble = ParseDoubleFromJValue(cValue);
102-
{
103-
if (cDouble.HasValue)
104-
{
105-
if (uDouble.Value > cDouble.Value) return true;
106-
}
107-
}
108-
}
109-
break;
47+
return NumericOperator(uValue, cValue, (a, b) => a > b);
11048
case "greaterThanOrEqual":
111-
uDouble = ParseDoubleFromJValue(uValue);
112-
if (uDouble.HasValue)
113-
{
114-
var cDouble = ParseDoubleFromJValue(cValue);
115-
{
116-
if (cDouble.HasValue)
117-
{
118-
if (uDouble.Value >= cDouble.Value) return true;
119-
}
120-
}
121-
}
122-
break;
49+
return NumericOperator(uValue, cValue, (a, b) => a >= b);
12350
case "before":
124-
uDateTime = JValueToDateTime(uValue);
125-
if (uDateTime.HasValue)
126-
{
127-
var cDateTime = JValueToDateTime(cValue);
128-
if (cDateTime.HasValue)
129-
{
130-
return DateTime.Compare(uDateTime.Value, cDateTime.Value) < 0;
131-
}
132-
}
133-
break;
51+
return DateOperator(uValue, cValue, (a, b) => DateTime.Compare(a, b) < 0);
13452
case "after":
135-
uDateTime = JValueToDateTime(uValue);
136-
if (uDateTime.HasValue)
137-
{
138-
var cDateTime = JValueToDateTime(cValue);
139-
if (cDateTime.HasValue)
140-
{
141-
return DateTime.Compare(uDateTime.Value, cDateTime.Value) > 0;
142-
}
143-
}
144-
break;
53+
return DateOperator(uValue, cValue, (a, b) => DateTime.Compare(a, b) > 0);
54+
case "semVerEqual":
55+
return SemVerOperator(uValue, cValue, (a, b) => a.ComparePrecedence(b) == 0);
56+
case "semVerLessThan":
57+
return SemVerOperator(uValue, cValue, (a, b) => a.ComparePrecedence(b) < 0);
58+
case "semVerGreaterThan":
59+
return SemVerOperator(uValue, cValue, (a, b) => a.ComparePrecedence(b) > 0);
14560
default:
14661
return false;
14762
}
@@ -158,6 +73,15 @@ public static bool Apply(string op, JValue uValue, JValue cValue)
15873
return false;
15974
}
16075

76+
private static bool StringOperator(JValue uValue, JValue cValue, Func<string, string, bool> fn)
77+
{
78+
if (uValue.Type.Equals(JTokenType.String) && cValue.Type.Equals(JTokenType.String))
79+
{
80+
return fn(uValue.Value<string>(), cValue.Value<string>());
81+
}
82+
return false;
83+
}
84+
16185
private static double? ParseDoubleFromJValue(JValue jValue)
16286
{
16387
if (jValue.Type.Equals(JTokenType.Float) || jValue.Type.Equals(JTokenType.Integer))
@@ -167,6 +91,27 @@ public static bool Apply(string op, JValue uValue, JValue cValue)
16791
return null;
16892
}
16993

94+
private static bool NumericOperator(JValue uValue, JValue cValue, Func<double, double, bool> fn)
95+
{
96+
var uDouble = ParseDoubleFromJValue(uValue);
97+
var cDouble = ParseDoubleFromJValue(cValue);
98+
return uDouble.HasValue && cDouble.HasValue && fn(uDouble.Value, cDouble.Value);
99+
}
100+
101+
private static bool DateOperator(JValue uValue, JValue cValue, Func<DateTime, DateTime, bool> fn)
102+
{
103+
var uDateTime = JValueToDateTime(uValue);
104+
var cDateTime = JValueToDateTime(cValue);
105+
return uDateTime.HasValue && cDateTime.HasValue && fn(uDateTime.Value, cDateTime.Value);
106+
}
107+
108+
private static bool SemVerOperator(JValue uValue, JValue cValue, Func<SemanticVersion, SemanticVersion, bool> fn)
109+
{
110+
var uVersion = JValueToSemVer(uValue);
111+
var cVersion = JValueToSemVer(cValue);
112+
return uVersion != null && cVersion != null && fn(uVersion, cVersion);
113+
}
114+
170115
//Visible for testing
171116
public static DateTime? JValueToDateTime(JValue jValue)
172117
{
@@ -186,5 +131,21 @@ public static bool Apply(string op, JValue uValue, JValue cValue)
186131
}
187132
return null;
188133
}
134+
135+
internal static SemanticVersion JValueToSemVer(JValue jValue)
136+
{
137+
if (jValue.Type == JTokenType.String)
138+
{
139+
try
140+
{
141+
return SemanticVersion.Parse(jValue.Value<String>(), allowMissingMinorAndPatch: true);
142+
}
143+
catch (ArgumentException)
144+
{
145+
return null;
146+
}
147+
}
148+
return null;
149+
}
189150
}
190151
}

0 commit comments

Comments
 (0)