private void GetArrayTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, IEnumerable value) { DataName typeName = this.GetTypeName(value); IEnumerator enumerator = value.GetEnumerator(); if (enumerator is IEnumerator <KeyValuePair <string, object> > ) { this.GetObjectTokens(tokens, detector, typeName, (IEnumerator <KeyValuePair <string, object> >)enumerator); return; } if (enumerator is IDictionaryEnumerator) { this.GetObjectTokens(tokens, detector, typeName, (IDictionaryEnumerator)enumerator); return; } tokens.Add(ModelGrammar.TokenArrayBegin(typeName)); while (enumerator.MoveNext()) { this.GetTokens(tokens, detector, enumerator.Current); } tokens.Add(ModelGrammar.TokenArrayEnd); }
public void Finds_Repeated_Number(Type detectorType) { ICycleDetector target = Activator.CreateInstance(detectorType) as ICycleDetector; int actual = target.Detect(this.onlyOneDuplicateNumber); Assert.AreEqual(3, actual); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, DataName typeName, IDictionaryEnumerator enumerator) { tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); while (enumerator.MoveNext()) { tokens.Add(ModelGrammar.TokenProperty(enumerator.Key)); this.GetTokens(tokens, detector, enumerator.Value); } tokens.Add(ModelGrammar.TokenObjectEnd); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, DataName typeName, IEnumerator <KeyValuePair <string, object> > enumerator) { tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); while (enumerator.MoveNext()) { KeyValuePair <string, object> pair = enumerator.Current; tokens.Add(ModelGrammar.TokenProperty(pair.Key)); this.GetTokens(tokens, detector, pair.Value); } tokens.Add(ModelGrammar.TokenObjectEnd); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, Type type, System.Dynamic.DynamicObject value) { DataName typeName = this.GetTypeName(value); tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); foreach (var memberName in value.GetDynamicMemberNames()) { object propertyValue; if (!value.TryGetMember(new DynamicGetter(memberName), out propertyValue)) { continue; } tokens.Add(ModelGrammar.TokenProperty(memberName)); this.GetTokens(tokens, detector, propertyValue); } tokens.Add(ModelGrammar.TokenObjectEnd); }
private void GetObjectTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, Type type, object value) { DataName typeName = this.GetTypeName(value); tokens.Add(ModelGrammar.TokenObjectBegin(typeName)); IDictionary <string, MemberMap> maps = this.Settings.Resolver.LoadMaps(type); if (maps == null) { // TODO: verify no other valid situations here tokens.Add(ModelGrammar.TokenObjectEnd); return; } // allow the resolver to optionally sort the members IEnumerable <MemberMap> members = this.Settings.Resolver.SortMembers(maps.Values); foreach (var map in members) { if (map.IsAlternate || map.Getter == null) { continue; } object propertyValue = map.Getter(value); if (map.IsIgnored != null && map.IsIgnored(value, propertyValue)) { continue; } tokens.Add(ModelGrammar.TokenProperty(map.DataName)); this.GetTokens(tokens, detector, propertyValue); } tokens.Add(ModelGrammar.TokenObjectEnd); }
public Graph(ICycleDetector <T> cycleDetector) { _cycleDetector = cycleDetector; }
private void GetTokens(List <Token <ModelTokenType> > tokens, ICycleDetector detector, object value) { if (value == null) { tokens.Add(ModelGrammar.TokenNull); return; } // test for cycles if (detector.Add(value)) { switch (this.Settings.GraphCycles) { case GraphCycleType.Reference: { // no need to remove value as was duplicate reference throw new GraphCycleException(GraphCycleType.Reference, "Graph cycle detected: repeated references"); } case GraphCycleType.MaxDepth: { throw new GraphCycleException(GraphCycleType.MaxDepth, "Graph cycle potentially detected: maximum depth exceeded"); } default: case GraphCycleType.Ignore: { // no need to remove value as was duplicate reference // replace cycle with null tokens.Add(ModelGrammar.TokenNull); return; } } } try { foreach (var filter in this.Filters) { IEnumerable <Token <ModelTokenType> > filterResult; if (filter.TryWrite(this.Settings, value, out filterResult)) { // found a successful match tokens.AddRange(filterResult); return; } } Type type = value.GetType(); // must test enumerations before other value types if (type.IsEnum) { tokens.Add(ModelGrammar.TokenPrimitive((Enum)value)); return; } // Type.GetTypeCode() allows us to more efficiently switch type switch (Type.GetTypeCode(type)) { case TypeCode.Boolean: { tokens.Add(true.Equals(value) ? ModelGrammar.TokenTrue : ModelGrammar.TokenFalse); return; } case TypeCode.Byte: case TypeCode.Decimal: case TypeCode.Int16: case TypeCode.Int32: case TypeCode.Int64: case TypeCode.SByte: case TypeCode.UInt16: case TypeCode.UInt32: case TypeCode.UInt64: { tokens.Add(ModelGrammar.TokenPrimitive((ValueType)value)); return; } case TypeCode.Double: { double doubleVal = (double)value; if (Double.IsNaN(doubleVal)) { tokens.Add(ModelGrammar.TokenNaN); } else if (Double.IsPositiveInfinity(doubleVal)) { tokens.Add(ModelGrammar.TokenPositiveInfinity); } else if (Double.IsNegativeInfinity(doubleVal)) { tokens.Add(ModelGrammar.TokenNegativeInfinity); } else { tokens.Add(ModelGrammar.TokenPrimitive(doubleVal)); } return; } case TypeCode.Single: { float floatVal = (float)value; if (Single.IsNaN(floatVal)) { // use the Double equivalent tokens.Add(ModelGrammar.TokenNaN); } else if (Single.IsPositiveInfinity(floatVal)) { // use the Double equivalent tokens.Add(ModelGrammar.TokenPositiveInfinity); } else if (Single.IsNegativeInfinity(floatVal)) { // use the Double equivalent tokens.Add(ModelGrammar.TokenNegativeInfinity); } else { tokens.Add(ModelGrammar.TokenPrimitive(floatVal)); } return; } case TypeCode.Char: case TypeCode.DateTime: case TypeCode.String: { tokens.Add(ModelGrammar.TokenPrimitive(value)); return; } case TypeCode.DBNull: case TypeCode.Empty: { tokens.Add(ModelGrammar.TokenNull); return; } } if (value is IEnumerable) { this.GetArrayTokens(tokens, detector, (IEnumerable)value); return; } if (value is Guid || value is Uri || value is Version) { tokens.Add(ModelGrammar.TokenPrimitive(value)); return; } if (value is TimeSpan) { tokens.Add(ModelGrammar.TokenPrimitive((TimeSpan)value)); return; } #if NET40 && !WINDOWS_PHONE if (value is System.Dynamic.DynamicObject) { // TODO: expand to all IDynamicMetaObjectProvider? this.GetObjectTokens(tokens, detector, type, (System.Dynamic.DynamicObject)value); return; } #endif // all other structs and classes this.GetObjectTokens(tokens, detector, type, value); } finally { detector.Remove(value); } }
/// <summary> /// Waits until evaluation gets cancelled or a value is set /// </summary> public void Wait(ICycleDetector cycleDetector = null) { lock (this) { if (m_result != EvaluationStatus.None) { return; } m_eventWaiters++; if (m_event == null) { m_event = new ManualResetEvent(false); } } if (cycleDetector == null) { m_event.WaitOne(); } else { // wait for evaluation in separate thread to finish m_event.WaitOne(m_startupDelay); // at first, wait for a reasonable amount of time without actually starting up cycle detector bool hasResult; lock (this) { hasResult = m_result != EvaluationStatus.None; } if (!hasResult) { // after the first delay, evaluation is still neither canceled nor finished; let's make sure the cycle detector is actually started up cycleDetector.EnsureStarted(); m_event.WaitOne(m_increasePriorityDelay); // second, wait for a reasonable amount of time without tinkering with priorities lock (this) { hasResult = m_result != EvaluationStatus.None; } if (!hasResult) { // after the second delay, evaluation is still neither canceled nor finished; let's raise priority of cycle detector while we keep waiting using (cycleDetector.IncreasePriority()) { m_event.WaitOne(); // third, just keep waiting until signaled, because of cancellation of because evaluation finishes } } } } lock (this) { Contract.Assume(m_result != EvaluationStatus.None); if (--m_eventWaiters == 0) { m_event.Dispose(); m_event = null; } } }