C# Client Library
A C# Client Library for the AnalyzeRe REST API
Loading...
Searching...
No Matches
Perspective.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Concurrent;
3using System.Collections.Generic;
4using System.Diagnostics;
5using System.Linq;
7
8namespace AnalyzeRe
9{
12 public class Perspective : APIType, IEquatable<Perspective>
13 {
14 #region Enumerations
22 [Flags]
54 #endregion Enumerations
55
56 #region Public Static Singletons
58 public static readonly Perspective LossGross = new Perspective(Base.LossGross);
59
61 public static readonly Perspective NetLoss = new Perspective(Base.NetLoss);
62
64 public static readonly Perspective Premium = new Perspective(Base.Premium);
65
67 public static readonly Perspective ReinstatementPremium = new Perspective(Base.ReinstatementPremium);
68
70 public static readonly Perspective ReinstatementBrokerage = new Perspective(Base.ReinstatementBrokerage);
71
73 public static readonly Perspective FixedExpense = new Perspective(Base.FixedExpense);
74
76 public static readonly Perspective ProportionalExpense = new Perspective(Base.ProportionalExpense);
77
79 public static readonly Perspective ProfitCommission = new Perspective(Base.ProfitCommission);
80
82 public static readonly Perspective NoClaimsBonus = new Perspective(Base.NoClaimsBonus);
83
85 public static readonly Perspective SlidingScaleCommission = new Perspective(Base.SlidingScaleCommission);
86
90 public static readonly Perspective LossNetOfAggregateTerms = new Perspective(Base.LossNetOfAggregateTerms);
91 #endregion Public Static Singletons
92
93 #region Private Properties
95 private readonly string[] _perspectiveSegments;
96
98 private readonly Lazy<string> _stringRepresentation;
99
103 private readonly Lazy<HashSet<string>> _uniqueElements;
104
106 private readonly Lazy<int> _hashCode;
107
108 #region Static Caches
111 private static readonly IEqualityComparer<HashSet<string>> SetComparer = HashSet<string>.CreateSetComparer();
112
120 private static readonly ConcurrentDictionary<string, Perspective> CachedComplexPerspectivesByString =
121 new ConcurrentDictionary<string, Perspective>(StringComparer.OrdinalIgnoreCase);
122 #endregion Static Caches
123 #endregion Private Properties
124
125 #region Constructors
129 private Perspective(string[] perspectiveSegments)
130 {
131 if (perspectiveSegments == null || perspectiveSegments.Length == 0)
132 throw new ArgumentException("At least one perspective value is required to instantiate a perspective.");
133 _perspectiveSegments = perspectiveSegments;
134 // The following internal members (once instantiated) will consume additional memory (when compared
135 // to computing these values on-the-fly), but have the beneficial trade-off of significantly improving
136 // the performance of repeatedly hashing, comparing, and serializing Perspective instances - which
137 // is generally expected to be the case when clients are using the provided static singleton instances,
138 // but also known to be the case within the Excel Add-In's current request architecture.
139 _stringRepresentation = new Lazy<string>(BuildStringRepresentation);
140 _uniqueElements = new Lazy<HashSet<string>>(BuildElementHashSet);
141 _hashCode = new Lazy<int>(ComputeHashCode);
142 }
143
148 private Perspective(Base[] perspectiveValues) :
149 this(perspectiveValues.Select(Enum<Base>.GetName).ToArray())
150 { }
151
153 private Perspective(Base perspectiveValue) : this(new[] { Enum<Base>.GetName(perspectiveValue) }) { }
154
155 #region Obsolete Public Constructors
161 [Obsolete("Use the static Perspective.FromString factory method so that cached immutable Perspectives can be returned.")]
162 public Perspective(string perspective) : this(SplitPerspectiveString(perspective).ToArray()) { }
163
172 [Obsolete("Use the static Perspective.FromEnums factory method. Perspectives are now built from any combination of Base enum values.")]
173 public Perspective(Base perspective_base, IEnumerable<Option> options = null) : this(new[] { perspective_base }
174 // Convert the legacy options into their corresponding "Base" enum values.
175 .Concat(options?.Select(o => o == Option.Premium ? Base.Premium :
177 Base.ReinstatementBrokerage) ?? Enumerable.Empty<Base>()).ToArray())
178 { }
179 #endregion Obsolete Public Constructors
180 #endregion Constructors
181
182 #region Public Static Factories
187 public static Perspective FromEnums(params Base[] perspectives) =>
188 perspectives != null && perspectives.Length > 0 ?
189 // Return the corresponding singleton if there is only a single value.
190 perspectives.Length == 1 ? FromEnum(perspectives[0]) :
191 // If is a complex perspective of multiple values, create a new Perspective instance
192 // TODO: This could benefit from caching, like the FromString factory, but only if we can quickly
193 // hash the incoming array of perspectives. (Compared to the time to instantiate a new Perspective)
194 new Perspective(perspectives) :
195 // If no values were provided, raise an exception
196 throw new ArgumentException("At least one perspective value is required to instantiate a perspective.");
197
202 public static Perspective FromEnums(IEnumerable<Base> perspectives) =>
203 FromEnums(perspectives?.ToArray() ?? new Base[] { });
204
207 public static Perspective FromEnum(Base perspective)
208 {
209 // Rather than constructing a new perspective instance, we can return
210 // one of the existing immutable perspective singletons (for performance)
211 switch (perspective)
212 {
213 case Base.LossGross: return LossGross;
214 case Base.NetLoss: return NetLoss;
217 case Base.Premium: return Premium;
218 case Base.FixedExpense: return FixedExpense;
221 case Base.NoClaimsBonus: return NoClaimsBonus;
223#pragma warning disable 618
225#pragma warning restore 618
226 default:
227 Debug.WriteLine($"The new perspective {perspective.ToString()} is missing " +
228 "from the enum to singleton converter. This has performance implications.");
229 return new Perspective(perspective);
230 }
231 }
232
240 public static Perspective LossNetOf(params Base[] perspectives) =>
241 FromEnums(new[] { Base.NetLoss }.Concat(perspectives).ToArray());
242
246 public static Perspective FromString(string perspectiveString)
247 {
248 return perspectiveString == null ? null :
249 // If the string matches a single perspective from the base enumeration,
250 // we can use the existing singleton for a big performance boost.
251 Enum<Base>.TryParse(perspectiveString, out Base parsed) ? FromEnum(parsed) :
252 // For complex perspectives, construct a new instance which will parse the string.
253 // Since there are a finite set of possible perspective combinations, and in practice
254 // the same combinations are used over and over, users can benefit from a dictionary
255 // that caches the immutable instance corresponding to each perspective string.
256 CachedComplexPerspectivesByString.GetOrAdd(perspectiveString,
257 newPerspectiveString => new Perspective(SplitPerspectiveString(newPerspectiveString).ToArray()));
258 }
259
263 public static implicit operator Perspective(string perspectiveString) => FromString(perspectiveString);
264
268 public static explicit operator Perspective(Base perspective) => FromEnum(perspective);
269 #endregion Public Static Factories
270
271 #region Private Methods
275 private string BuildStringRepresentation() =>
276 _perspectiveSegments.Length == 1 ? _perspectiveSegments[0] : String.Join(",", _perspectiveSegments);
277
281 private HashSet<string> BuildElementHashSet() =>
282 new HashSet<string>(_perspectiveSegments, StringComparer.OrdinalIgnoreCase);
283
285 private int ComputeHashCode() => SetComparer.GetHashCode(_uniqueElements.Value);
286
289 private static readonly char[] SplitChars = { ',', '[', ']' };
290
292 private static IEnumerable<string> SplitPerspectiveString(string perspectiveString) =>
293 perspectiveString.Split(SplitChars, StringSplitOptions.RemoveEmptyEntries)
294 // For backwards-compatibility purposes, we must attempt to parse each value with our enumeration
295 // (case insensitive), and convert to the proper-case string representation if successful.
296 // This is because the server is case-sensitive while historically the C# client has not been.
297 // Note that we still use strings as the final internal representation, because we wish to be
298 // forward-compatible with newly added perspectives that have not yet been surfaced in C#,
299 // hence the fall-back rule to use the string as-is when the Enum.TryParse fails.
300 .Select(s => Enum<Base>.TryParse(s, out Base persp) ? Enum<Base>.GetName(persp) : s);
301 #endregion Private Methods
302
303 #region Overrides
305 public override string ToString() => _stringRepresentation.Value;
306
309 public override int GetHashCode() => _hashCode.Value;
310
314 public bool Equals(Perspective other)
315 {
316 // First, test for reference equality (should often be true since we use static singletons where possible)
317 if (ReferenceEquals(this, other)) return true;
318 if (other == null) return false;
319 // A fast test is whether the string representations (already built) are equal
320 return String.Equals(_stringRepresentation.Value, other._stringRepresentation.Value, StringComparison.Ordinal) ||
321 // Failing that, we can only be certain by using our case-insensitive HashSet of perspective components
322 SetComparer.Equals(_uniqueElements.Value, other._uniqueElements.Value);
323 }
324
328 public override bool Equals(object other) =>
329 ReferenceEquals(this, other) ||
330 other is Perspective persp && Equals(persp) ||
331 // Note: The value of comparing other types in this way is questionable since most
332 // applications will deny the equivalence of two objects if their types aren't equal
333 // and/or reject covariantly incompatible types being compared at compile time.
334 // Still, for backwards-compatibility with the previous implementation, we leave this in place.
335 other is Base enumValue && Equals(FromEnum(enumValue)) ||
336 other is string perspString && Equals(FromString(perspString));
337 #endregion Overrides
338
339 #region Obsolete
341 [Obsolete("Perspectives are now simply built from any combination of Base enum values.")]
342 public enum Option
343 {
345 Premium,
350 }
351
353 [Obsolete("A cached string representation can simply be returned by calling ToString()")]
354 public static string GetStringRepresentation(Perspective persp) => persp._stringRepresentation.Value;
355
363 public static Perspective LossNetOfAggregateTermsAnd(bool premium = false,
364 bool reinstatement_premium = false, bool reinstatement_brokerage = false)
365 {
366 // Use a static singleton if possible.
367 if (!premium && !reinstatement_premium && !reinstatement_brokerage)
369 // No need to continue using the legacy options or constructor, because the internal representation ends up the same
370 List<Base> perspectives = new List<Base> { Base.LossNetOfAggregateTerms };
371 if (premium) perspectives.Add(Base.Premium);
372 if (reinstatement_premium) perspectives.Add(Base.ReinstatementPremium);
373 if (reinstatement_brokerage) perspectives.Add(Base.ReinstatementBrokerage);
374 return FromEnums(perspectives);
375 }
376 #endregion Obsolete
377 }
378}
Base class used by all types and resources.
Definition APIType.cs:8
The loss perspective determines what factors to include when computing a distribution.
static readonly Perspective ReinstatementBrokerage
Construct a distribution from the structure's net reinstatement brokerages.
static Perspective FromEnum(Base perspective)
Returns the appropriate singleton for the Base perspective given.
static readonly Perspective SlidingScaleCommission
Report on the structure's Fees.FixedExpense fees.
static string GetStringRepresentation(Perspective persp)
Generate a string representation of the specified perspective.
static readonly Perspective LossGross
Construct a distribution from the structure's gross losses.
static Perspective LossNetOf(params Base[] perspectives)
A convenience static method, similar to the other static singletons, which constructs a complex persp...
override string ToString()
Perspective string is just the class name.
static Perspective FromEnums(IEnumerable< Base > perspectives)
Construct a new Perspective that should include the specified Base perspective values.
override bool Equals(object other)
Tests object equality.
static readonly Perspective ProportionalExpense
Report on the structure's Fees.ProportionalExpense fees.
bool Equals(Perspective other)
Determine whether the two perspectives are equivalent.
Perspective(string perspective)
Construct a new perspective from a serialized perspective string.
static readonly Perspective FixedExpense
Report on the structure's Fees.FixedExpense fees.
static readonly Perspective NetLoss
Construct a distribution from the structure's net losses.
override int GetHashCode()
Serves as a hash function for a particular type.
static readonly Perspective LossNetOfAggregateTerms
The legacy perspective value indicating "net loss" - but this includes fee record types as well.
static readonly Perspective NoClaimsBonus
Report on the structure's Fees.FixedExpense fees.
Base
The set of available values and RecordTypes that can be used to construct a distribution or metrics r...
static Perspective FromString(string perspectiveString)
Implicit converter that allows automatically converting a string into a perspective,...
static Perspective LossNetOfAggregateTermsAnd(bool premium=false, bool reinstatement_premium=false, bool reinstatement_brokerage=false)
Constructs a legacy LossNetOfAggregateTerms[X,Y,Z] perspective, where you can specify which values to...
Option
The options to include in the base perspective distribution.
static readonly Perspective Premium
Report on the structure's premium only.
Perspective(Base perspective_base, IEnumerable< Option > options=null)
Constructs a legacy perspective string.
static readonly Perspective ReinstatementPremium
Construct a distribution from the structure's net reinstatement premiums.
static readonly Perspective ProfitCommission
Report on the structure's Fees.FixedExpense fees.
static Perspective FromEnums(params Base[] perspectives)
Construct a new Perspective that should include the specified Base perspective value or values.
Helper class for extending the functionality of the static Enumclass with compile-time-type-specific ...
Definition Enum.cs:11
static string GetName(T value)
Convert the enumeration value to a string.
static bool TryParse(string value, out T result)
Try to convert the string to an enumeration value.