/// <summary> /// Registers a type definition with this dictionary. Additional .NET types can be passed that will be translated to the /// type referenced in the type definition. If a type with same numeric type identifier is already in the dictionary it /// will be replaced. /// </summary> /// <param name="type">type definition</param> /// <param name="alternativeTypes">alternative .NET types that map to this type</param> public void AddType(FudgeFieldType type, params Type[] alternativeTypes) { if (type == null) { throw new ArgumentNullException("Must not provide a null FudgeFieldType to add."); } rwLock.AcquireWriterLock(Timeout.Infinite); try { if (!(type is ISecondaryFieldType)) { int newLength = Math.Max(type.TypeId + 1, typesById.Length); var newArray = new FudgeFieldType[newLength]; typesById.CopyTo(newArray, 0); newArray[type.TypeId] = type; typesById = newArray; } // TODO 2009-12-14 Andrew -- the secondary type mechanism needs review; not sure how best to do it in Java and I would like to keep the APIs similar in spirit typesByCSharpType[type.CSharpType] = type; foreach (Type alternativeType in alternativeTypes) { typesByCSharpType[alternativeType] = type; } } finally { rwLock.ReleaseWriterLock(); } }
/// <inheritdoc /> public virtual void Add(string name, int?ordinal, FudgeFieldType type, object value) { if (ordinal.HasValue && (ordinal < short.MinValue || ordinal > short.MaxValue)) { throw new ArgumentOutOfRangeException("ordinal", "Ordinal must be within signed 16-bit range"); } if (type == null) { // See if we can derive it type = context.TypeHandler.DetermineTypeFromValue(value); if (type == null) { throw new ArgumentException("Cannot determine a Fudge type for value " + value + " of type " + value.GetType()); } } if (type == FudgeMsgFieldType.Instance && !(value is FudgeMsg)) { // Copy the fields across to a new message value = CopyContainer((IFudgeFieldContainer)value); } // Adjust values to the lowest possible representation. value = type.Minimize(value, ref type); FudgeMsgField field = new FudgeMsgField(type, value, name, (short?)ordinal); fields.Add(field); }
/// <inheritdoc/> public override object Minimize(object value, ref FudgeFieldType type) { type = wireType; object newValue = outputConverter((T)value); return(wireType.Minimize(newValue, ref type)); // Allow the wire type to minimise further if it wants }
/// <summary> /// Gets the .NET name of a <c>FudgeFieldType</c> object. /// </summary> /// <param name="type"></param> /// <returns></returns> protected string GetTypeName(FudgeFieldType type) { if (type == null) { throw new NullReferenceException("Must specify a type."); } return(type.CSharpType.Name); }
/// <summary> /// Creates a new message field. /// </summary> /// <param name="type">field data type</param> /// <param name="value">field value</param> /// <param name="name">field name, or null for no field name</param> /// <param name="ordinal">ordinal index, or null for no ordinal index</param> public FudgeMsgField(FudgeFieldType type, object value, string name, short?ordinal) { if (type == null) { throw new ArgumentNullException("Must specify a type for this field."); } this.type = type; this.value = value; this.name = name; this.ordinal = ordinal; }
/// <summary> /// Creates a new message field. /// </summary> /// <param name="type">field data type</param> /// <param name="value">field value</param> /// <param name="name">field name, or null for no field name</param> /// <param name="ordinal">ordinal index, or null for no ordinal index</param> public FudgeMsgField(FudgeFieldType type, object value, string name, short? ordinal) { if (type == null) { throw new ArgumentNullException("Must specify a type for this field."); } this.type = type; this.value = value; this.name = name; this.ordinal = ordinal; }
/// <summary> /// Returns the type definition most appropiate for a value type. /// </summary> /// <param name="csharpType">type of a value</param> /// <returns>type definition</returns> public FudgeFieldType GetByCSharpType(Type csharpType) { if (csharpType == null) { return null; } rwLock.AcquireReaderLock(Timeout.Infinite); FudgeFieldType result = null; typesByCSharpType.TryGetValue(csharpType, out result); rwLock.ReleaseReaderLock(); return result; }
/// <summary> /// Cosntructs a new <c>SeondaryFieldType</c> without conversion functions. /// </summary> /// <param name="wireType">Canonical type that values of this type will be represented as when encoded.</param> /// <remarks> /// Derived types can use this form if they wish to override <see cref="Minimize"/> and <see cref="ConvertValueFrom"/> /// directly rather than supplying conversion functions. /// </remarks> protected SecondaryFieldType(FudgeFieldType wireType) : base(wireType.TypeId, wireType.IsVariableSize, wireType.FixedSize) { if (wireType == null) { throw new ArgumentNullException("wireType"); } if (wireType.CSharpType != typeof(RawType)) { throw new ArgumentException("wireType does not match RawType for " + GetType().Name); } // Use overrides instead of delegates this.inputConverter = (raw => ConvertFromWire(raw)); this.outputConverter = (value => ConvertToWire(value)); }
/// <summary> /// Tests if this object is equal to another. Two <c>FudgeFieldType</c>s are equal iff they have the same numeric type identifier. /// </summary> /// <param name="obj">the object to compare to</param> /// <returns>true iff the objects are equal</returns> public override bool Equals(object obj) { if (obj == this) { return(true); } FudgeFieldType other = obj as FudgeFieldType; if (other == null) { return(false); } if (TypeId != other.TypeId) { return(false); } // Don't bother checking the rest of it. return(true); }
/// <summary> /// Determines the <c>FudgeFieldType</c> of a C# value. /// </summary> /// <param name="value">value whose type is to be determined</param> /// <returns>the appropriate <c>FudgeFieldType</c> instance</returns> public FudgeFieldType DetermineTypeFromValue(object value) { if (value == null) { throw new ArgumentNullException("Cannot determine type for null value."); } FudgeFieldType type = typeDictionary.GetByCSharpType(value.GetType()); if (type == null) { // Couple of special cases if (value is UnknownFudgeFieldValue) { UnknownFudgeFieldValue unknownValue = (UnknownFudgeFieldValue)value; type = unknownValue.Type; } else if (value is IFudgeFieldContainer) { type = FudgeMsgFieldType.Instance; } } return(type); }
/// <summary> /// Converts the supplied value to a base type using the corresponding FudgeFieldType definition. The supplied .NET type /// is resolved to a registered FudgeFieldType. The <c>ConvertValueFrom</c> method on the registered type is then used /// to convert the value. /// </summary> /// <param name="value">value to convert</param> /// <param name="type">.NET target type</param> /// <returns>the converted value</returns> public object ConvertType(object value, Type type) { if (value == null) { return(null); } if (value.GetType() == type) { return(value); } if (!type.IsAssignableFrom(value.GetType())) { FudgeFieldType fieldType = typeDictionary.GetByCSharpType(type); if (fieldType == null) { throw new InvalidCastException("No registered field type for " + type.Name); } value = fieldType.ConvertValueFrom(value); } return(value); }
/// <summary> /// Cosntructs a new <c>SeondaryFieldType</c>. /// </summary> /// <param name="wireType">Canonical type that values of this type will be represented as when encoded.</param> /// <param name="inputConverter">Function to convert values from canonical type to this type.</param> /// <param name="outputConverter">Function to convert values from this type to the canonical type.</param> public SecondaryFieldType(FudgeFieldType wireType, Converter <RawType, T> inputConverter, Converter <T, RawType> outputConverter) : base(wireType.TypeId, wireType.IsVariableSize, wireType.FixedSize) { if (wireType == null) { throw new ArgumentNullException("wireType"); } if (inputConverter == null) { throw new ArgumentNullException("inputConverter"); } if (outputConverter == null) { throw new ArgumentNullException("outputConverter"); } if (wireType.CSharpType != typeof(RawType)) { throw new ArgumentException("wireType does not match RawType for " + GetType().Name); } this.wireType = wireType; this.inputConverter = inputConverter; this.outputConverter = outputConverter; }
/// <summary> /// Override <c>Minimize</c> where you wish to be able to reduce to a lower type as fields are added to messages. /// </summary> /// <remarks> /// <c>Minimize</c> is used to reduce integers to their smallest form, but can also be used to convert /// non-primitive types (e.g. GUID) to primitive ones (e.g. byte[16]) as they are added. /// </remarks> /// <param name="value">Value to reduce.</param> /// <param name="type">Current field type - update this if you minimize to a different type.</param> /// <returns>Minimized value.</returns> public virtual object Minimize(object value, ref FudgeFieldType type) { return(value); }
/// <summary> /// Gets the .NET name of a <c>FudgeFieldType</c> object. /// </summary> /// <param name="type"></param> /// <returns></returns> protected string GetTypeName(FudgeFieldType type) { if (type == null) { throw new NullReferenceException("Must specify a type."); } return type.CSharpType.Name; }
/// <summary> /// Override <c>Minimize</c> where you wish to be able to reduce to a lower type as fields are added to messages. /// </summary> /// <remarks> /// <c>Minimize</c> is used to reduce integers to their smallest form, but can also be used to convert /// non-primitive types (e.g. GUID) to primitive ones (e.g. byte[16]) as they are added. /// </remarks> /// <param name="value">Value to reduce.</param> /// <param name="type">Current field type - update this if you minimize to a different type.</param> /// <returns>Minimized value.</returns> public virtual object Minimize(object value, ref FudgeFieldType type) { return value; }