/// <summary> /// Convert class into a list of generic entries using custom strategy /// </summary> public static Entry EncodeClass(Type objType, ICustomSerialization customSerialization) { var encodedClass = CreateFromType(objType, customSerialization); var filtered = customSerialization.GetProperties(objType); foreach (var property in filtered) { var converted = EncodeProperty(property, customSerialization); // Assign default to current var value = converted.Value; value.Current = ConvertToString(value.Default, customSerialization.FormatProvider); // Recursive call for classes if (converted.Value.Type == EntryValueType.Class) { // Convert sub entries for classes var subentry = EncodeClass(property.PropertyType, customSerialization); converted.SubEntries.AddRange(subentry.SubEntries); } encodedClass.SubEntries.Add(converted); } return(encodedClass); }
/// <summary> /// Create strategy for collection /// </summary> private static ICollectionStrategy CreateStrategy(object collection, object currentCollection, Type collectionType, ICustomSerialization serialization, ICustomAttributeProvider attributeProvider = null, object instance = null) { ICollectionStrategy strategy; if (collectionType.IsArray) { strategy = new ArrayStrategy((Array)collection, currentCollection as Array, serialization); } else if (collection is IDictionary) { strategy = new DictionaryStrategy((IDictionary)collection, serialization); } else if (collection is IList) { if (currentCollection is Array) { strategy = new ArrayIListStrategy( (IList)collection, serialization, attributeProvider, instance); } else { strategy = new ListStrategy((IList)collection, serialization); } } else { throw new InvalidOperationException($"Unsupported collection type {collectionType}"); } return(strategy); }
/// <summary> /// Create a prototype entry for a certain type /// </summary> public static Entry Prototype(EntryPrototype type, ICustomSerialization customSerialization) { Entry encoded; var transformedType = TransformType(type.Prototype.GetType()); if (transformedType != EntryValueType.Class) { var value = type.Prototype.ToString(); var valueType = type.Prototype.GetType(); encoded = new Entry { DisplayName = valueType.Name, Identifier = Entry.CreatedIdentifier, Value = new EntryValue { Current = value, Default = value, Type = TransformType(valueType) } }; } else { encoded = EncodeObject(type.Prototype, customSerialization); } return(encoded); }
/// <summary> /// Convert a single property into a derived type of entry using a custom strategy /// </summary> /// <returns>Converted property</returns> public static Entry EncodeProperty(PropertyInfo property, ICustomSerialization customSerialization) { // Fill with default if entry is null var entry = new Entry { DisplayName = property.GetDisplayName() ?? property.Name, Identifier = property.Name, Description = property.GetDescription(), Value = CreateEntryValue(property, customSerialization), Validation = customSerialization.CreateValidation(property.PropertyType, property) }; // No prototypes for readonly entries or entries without flexible sub-entries if (entry.Value.IsReadOnly || entry.Value.Type != EntryValueType.Collection && entry.Value.Type != EntryValueType.Class) { return(entry); } // Determine and convert prototypes var prototypes = Prototypes(property.PropertyType, property, customSerialization); entry.Prototypes.AddRange(prototypes); return(entry); }
public HttpClientWrapper( HttpClient httpClient, ICustomSerialization customSerialization) { HttpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); CustomSerialization = customSerialization ?? throw new ArgumentNullException(nameof(customSerialization)); }
/// <summary> /// Create typed instance from encoded properties /// </summary> public static T CreateInstance <T>(Entry encoded, ICustomSerialization customSerialization) where T : class, new() { var instance = new T(); UpdateInstance(instance, encoded, customSerialization); return(instance); }
public ArrayIListStrategy(IList list, ICustomSerialization customSerialization, ICustomAttributeProvider attributeProvider, object instance) { _list = list; _customSerialization = customSerialization; _property = attributeProvider; _instance = instance; }
/// <summary> /// Create entry for object from collection /// </summary> public static Entry CreateSub(object item, int index, ICustomSerialization customSerialization) { var subEntry = EntryConvert.EncodeObject(item, customSerialization); subEntry.DisplayName = GetEntryName(item); subEntry.Identifier = index.ToString("D"); return(subEntry); }
/// <summary> /// Update existing object from encoded values /// </summary> public static object UpdateInstance(object instance, Entry encoded, ICustomSerialization customSerialization) { var filtered = customSerialization.WriteFilter(instance.GetType(), encoded.SubEntries); foreach (var mapped in filtered) { var property = mapped.Property; var propertyType = mapped.Property.PropertyType; var doNotUpdateProperty = false; // Do not operate on faulty properties or read-only properties // For security reasons read the flag from the property again if (mapped.Entry?.Value.Type == EntryValueType.Exception || property.GetCustomAttribute <ReadOnlyAttribute>()?.IsReadOnly == true) { continue; } // Try to assign value to the property var currentValue = mapped.Property.GetValue(instance); var value = mapped.Entry == null ? customSerialization.DefaultValue(property, currentValue) : customSerialization.ConvertValue(propertyType, property, mapped.Entry, currentValue); // Value types, strings and streams do not need recursion if (ValueOrStringType(propertyType) || typeof(Stream).IsAssignableFrom(propertyType)) { } // Update collection from entry else if (IsCollection(propertyType) && mapped.Entry != null) { // Pick collection strategy var strategy = CreateStrategy(value, currentValue, propertyType, customSerialization, mapped.Property, instance); UpdateCollection(currentValue, mapped.Property.PropertyType, mapped.Property, mapped.Entry, strategy, customSerialization); if (strategy is ArrayIListStrategy) { doNotUpdateProperty = true; } } // Update class else if (propertyType.IsClass) { UpdateInstance(value, mapped.Entry ?? new Entry(), customSerialization); } else { throw new SerializationException($"Unsupported property {property.Name} on {instance.GetType().Name}!"); } // Write new value to property if (property.CanWrite && !doNotUpdateProperty) { mapped.Property.SetValue(instance, value); } } return(instance); }
/// <summary> /// Invoke a method on the target object using custom customSerialization /// </summary> public static Entry InvokeMethod(object target, MethodEntry methodEntry, ICustomSerialization customSerialization) { var method = target.GetType().GetMethods() .First(m => m.Name == methodEntry.Name && ParametersProvided(m.GetParameters(), methodEntry)); var arguments = ConvertArguments(method, methodEntry, customSerialization); var result = method.Invoke(target, arguments); return(result == null ? null : EncodeObject(result, customSerialization)); }
/// <summary> /// Update or fill the collection using the mapping entry /// </summary> private static void UpdateCollection(object currentValue, Type memberType, ICustomAttributeProvider attributeProvider, Entry rootEntry, ICollectionStrategy strategy, ICustomSerialization customSerialization) { var currentCollection = currentValue as ICollection; // Loop over the collection and update the entries that are still present if (currentCollection != null) { foreach (var key in strategy.Keys()) { var item = strategy.ElementAt(key); var match = rootEntry.SubEntries.Find(se => se.Identifier == key); if (match == null) { strategy.Removed(key); continue; } if (match.Value.Type < EntryValueType.Class) { item = CreatePrimitiveOrEnum(memberType, match.Value, customSerialization.FormatProvider); } else { UpdateInstance(item, match, customSerialization); } strategy.Updated(match, item); } } // Add new entries to the collection foreach (var subEntry in rootEntry.SubEntries.Where(se => se.Identifier == Entry.CreatedIdentifier)) { object item; // All value types if (subEntry.Value.Type < EntryValueType.Class) { // Create value type item = CreatePrimitiveOrEnum(memberType, subEntry.Value, customSerialization.FormatProvider); } else { // Create and update reference types item = customSerialization.CreateInstance(memberType, attributeProvider, subEntry); item = UpdateInstance(item, subEntry, customSerialization); } strategy.Added(subEntry, item); } // Finalize all operations strategy.Flush(); }
public void Serialize(Stream stream, BinaryWriter writer) { writer.Write(m_customSerializationAssets.Count); for (int i = 0; i < m_customSerializationAssets.Count; ++i) { ICustomSerialization asset = m_customSerializationAssets[i]; writer.Write(asset.AllowStandardSerialization); writer.Write(m_customSerializationAssetIndices[i]); writer.Write(m_typeMap.ToGuid(asset.GetType()).ToByteArray()); asset.Serialize(stream, writer); } m_customSerializationAssets = null; m_customSerializationAssetIndices = null; }
/// <see cref="ICustomSerialization"/> private static EntryValue CreateEntryValue(PropertyInfo property, ICustomSerialization customSerialization) { // Set if the current entry is readonly by checking if the property has a setter // or the ReadOnlyAttribute was set to true var isReadOnly = !property.CanWrite; if (!isReadOnly) { var readOnlyAtt = property.GetCustomAttribute <ReadOnlyAttribute>(); isReadOnly = readOnlyAtt?.IsReadOnly ?? false; } // Prepare object var entryValue = new EntryValue { Type = TransformType(property.PropertyType), UnitType = customSerialization.GetUnitTypeByAttributes(property), IsReadOnly = isReadOnly, Possible = customSerialization.PossibleValues(property.PropertyType, property) }; // Get most basic default var defaultAttribute = property.GetCustomAttribute <DefaultValueAttribute>(); if (defaultAttribute != null) { entryValue.Default = defaultAttribute.Value.ToString(); } else if (entryValue.Possible != null && entryValue.Possible.Length >= 1) { entryValue.Default = entryValue.Possible[0]; } else if (property.PropertyType.IsValueType) { entryValue.Default = Activator.CreateInstance(property.PropertyType).ToString(); } // Value types should have the default value as current value if (ValueOrStringType(property.PropertyType)) { entryValue.Current = ConvertToString(entryValue.Default, customSerialization.FormatProvider); } return(entryValue); }
/// <summary> /// Create basic <see cref="Entry"/> instance for a given object type /// </summary> private static Entry CreateFromType(Type objectType, ICustomSerialization serialization) { var entry = new Entry { DisplayName = objectType.GetDisplayName() ?? objectType.Name, Identifier = objectType.Name, Value = new EntryValue { Current = objectType.Name, Default = objectType.Name, Type = TransformType(objectType) }, Validation = serialization.CreateValidation(objectType, objectType), Description = objectType.GetDescription() }; return(entry); }
/// <summary> /// Encode a <see cref="MethodBase"/> to the transmittable <see cref="MethodEntry"/> /// </summary> public static MethodEntry EncodeMethod(MethodBase method, ICustomSerialization serialization) { return(new MethodEntry { Name = method.Name, IsConstructor = method.IsConstructor, DisplayName = method.GetDisplayName() ?? method.Name, Description = method.GetDescription(), Parameters = new Entry { DisplayName = "Root", Identifier = "Root", Value = new EntryValue { Type = EntryValueType.Class }, SubEntries = method.GetParameters().Select(p => ConvertParameter(p, serialization)).ToList() } }); }
/// <summary> /// Checks if resource and model are equal /// </summary> /// <param name="resource"></param> /// <param name="serialization"></param> /// <returns></returns> internal bool DifferentFrom(Resource resource, ICustomSerialization serialization) { // Do not compare values that were not transmitted if (resource.Descriptor == null || PartiallyLoaded) { return(false); } // Compare obvious base properties var different = resource.Name != Name || resource.Description != Description; if (different) { return(true); } var resourceProperties = EntryConvert.EncodeObject(resource.Descriptor, serialization); return(!Entry.ValuesEqual(Properties, resourceProperties)); }
/// <summary> /// Convert a single property into a derived type of entry using a custom strategy /// </summary> /// <returns>Covnerted property</returns> public static Entry EncodeProperty(PropertyInfo property, ICustomSerialization customSerialization) { // Fill with default if entry is null var entry = new Entry { DisplayName = property.GetDisplayName() ?? property.Name, Identifier = property.Name, Description = property.GetDescription(), Value = CreateEntryValue(property, customSerialization), Validation = customSerialization.CreateValidation(property.PropertyType, property) }; // Include prototypes for collections and classes if (entry.Value.Type == EntryValueType.Collection || entry.Value.Type == EntryValueType.Class) { var prototypes = Prototypes(property.PropertyType, property, customSerialization); entry.Prototypes.AddRange(prototypes); } return(entry); }
/// <summary> /// Convert a method parameter to our standard <see cref="Entry"/> format /// </summary> private static Entry ConvertParameter(ParameterInfo parameter, ICustomSerialization serialization) { var parameterType = parameter.ParameterType; var defaultValue = parameter.HasDefaultValue ? parameter.DefaultValue.ToString() : null; var parameterModel = new Entry { DisplayName = parameter.GetDisplayName() ?? parameter.Name, Identifier = parameter.Name, Description = parameter.GetDescription(), Value = new EntryValue { Type = TransformType(parameter.ParameterType), UnitType = serialization.GetUnitTypeByAttributes(parameter), Current = defaultValue, Default = defaultValue, Possible = serialization.PossibleValues(parameterType, parameter) }, Validation = serialization.CreateValidation(parameterType, parameter) }; switch (parameterModel.Value.Type) { case EntryValueType.Class: parameterModel.Value.Current = parameterType.Name; parameterModel.Prototypes.AddRange(Prototypes(parameterType, parameter, serialization)); parameterModel.SubEntries = EncodeClass(parameterType, serialization).SubEntries; break; case EntryValueType.Collection: var elemType = ElementType(parameterType); parameterModel.Value.Current = elemType.Name; parameterModel.Prototypes.AddRange(Prototypes(parameterType, parameter, serialization)); break; } return(parameterModel); }
private static byte[] serializeObject(Object o) { byte[] result = null; byte[] serialized = null; if (o is ICustomSerialization) { ICustomSerialization serializable = o as ICustomSerialization; serialized = serializable.toByteArray(); } else { serialized = Converter.ObjectToByteArray(o); } int length = serialized.Length; byte[] lenArr = Converter.toByteArray(length); result = Combine(lenArr, serialized); return(result); }
public void OnBeforeSerialization() { if (!RTSLSettings.IsCustomSerializationEnabled) { return; } m_customSerializationAssets = new List <ICustomSerialization>(); m_customSerializationAssetIndices = new List <int>(); for (int i = 0; i < Assets.Length; ++i) { ICustomSerialization asset = Assets[i] as ICustomSerialization; if (asset != null) { m_customSerializationAssets.Add(asset); m_customSerializationAssetIndices.Add(i); if (!asset.AllowStandardSerialization) { Assets[i] = null; } } } }
public ArrayStrategy(Array array, Array currentArray, ICustomSerialization serialization) { _array = array; _currentArray = currentArray; _serialization = serialization; }
/// <summary> /// Constructor /// </summary> /// <param name="resourceGraph"></param> /// <param name="serialization"></param> public ModelToResourceConverter(IResourceGraph resourceGraph, ICustomSerialization serialization) { _resourceGraph = resourceGraph; _serialization = serialization; }
/// <summary> /// Convert encoded parameters to argument array for method invocation /// </summary> private static object[] ConvertArguments(MethodBase method, MethodEntry encodedMethod, ICustomSerialization customSerialization) { var parameters = method.GetParameters(); var arguments = new object[parameters.Length]; var parameterEntries = encodedMethod.Parameters.SubEntries; for (var i = 0; i < parameters.Length; i++) { var entry = parameterEntries[i]; var parameter = parameters[i]; var paramType = parameter.ParameterType; var argument = customSerialization.ConvertValue(paramType, parameter, entry, null); // Value types and strings do not need recursion if (ValueOrStringType(paramType)) { } // Update collection from entry else if (argument is ICollection && entry != null) { // Pick collection strategy var strategy = CreateStrategy(argument, null, paramType, customSerialization); UpdateCollection(null, paramType, parameter, entry, strategy, customSerialization); } // Update class else if (paramType.IsClass) { if (entry == null) { UpdateInstance(argument, new Entry(), customSerialization); } else { UpdateInstance(argument, entry, customSerialization); } } arguments[i] = argument; } return(arguments); }
/// <summary> /// Encode all methods of a type using a custom customSerialization /// </summary> public static IEnumerable <MethodEntry> EncodeMethods(Type objType, ICustomSerialization serialization) { var methods = serialization.GetMethods(objType); return(methods.Select(m => EncodeMethod(m, serialization))); }
/// <summary> /// Encode all constructors of a class /// </summary> public static IEnumerable <MethodEntry> EncodeConstructors(Type objType, ICustomSerialization serialization) { var constructors = objType.GetConstructors(); return(constructors.Select(c => EncodeMethod(c, serialization))); }
public void SerializeResponse(XmlWriter writer, object value, XRoadMessage message, XmlReader requestReader, ICustomSerialization customSerialization = null) { var containsRequest = requestReader.MoveToElement(2, OperationDefinition.Name); if (containsRequest) { writer.WriteStartElement(requestReader.Prefix, $"{OperationDefinition.Name.LocalName}Response", OperationDefinition.Name.NamespaceName); } else { writer.WriteStartElement($"{OperationDefinition.Name.LocalName}Response", OperationDefinition.Name.NamespaceName); } writer.WriteEndElement(); }
public ResourceQueryConverter(IResourceTypeTree typeController, ICustomSerialization serialization, ResourceQuery query) : base(typeController, serialization) { Query = query; }
/// <summary> /// Create object instance from config model using entry for specialized types /// </summary> public static object CreateInstance(Type type, Entry encoded, ICustomSerialization customSerialization) { var instance = customSerialization.CreateInstance(type, encoded); return(UpdateInstance(instance, encoded, customSerialization)); }
/// <summary> /// Serializes `listMethods` response. /// </summary> public void SerializeResponse(XmlWriter writer, object value, XRoadMessage message, XmlReader requestReader, ICustomSerialization customSerialization = null) { var containsRequest = requestReader.MoveToElement(2, OperationDefinition.Name.LocalName, OperationDefinition.Name.NamespaceName); if (containsRequest) { writer.WriteStartElement(requestReader.Prefix, $"{OperationDefinition.Name.LocalName}Response", OperationDefinition.Name.NamespaceName); } else { writer.WriteStartElement($"{OperationDefinition.Name.LocalName}Response", OperationDefinition.Name.NamespaceName); } var namespaceInContext = requestReader.NamespaceURI; var responsePartName = OperationDefinition.Name.NamespaceName.Equals(NamespaceConstants.XTEE) ? "keha" : "response"; var style = OperationDefinition.Name.NamespaceName.Equals(NamespaceConstants.XTEE) ? (Style) new RpcEncodedStyle() : new DocLiteralStyle(); if (Equals(namespaceInContext, "")) { writer.WriteStartElement(responsePartName); } else { writer.WriteStartElement(responsePartName, ""); } var typeName = XName.Get("string", NamespaceConstants.XSD); var methodNames = value as ICollection <string> ?? new string[0]; style.WriteExplicitArrayType(writer, typeName, methodNames.Count); foreach (var methodName in methodNames) { writer.WriteStartElement("item"); style.WriteExplicitType(writer, typeName); writer.WriteString(methodName); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndElement(); }
/// <summary> /// Create object instance from config model using entry for specialized types /// </summary> public static object CreateInstance(Type type, MethodEntry encodedConstructor, ICustomSerialization customSerialization) { // Retrieve the most specific constructor matched by the encoded method entry var constructor = (from ctor in type.GetConstructors() let parameters = ctor.GetParameters() where parameters.Length == encodedConstructor.Parameters.SubEntries.Count && ParametersProvided(parameters, encodedConstructor) select ctor).First(); var arguments = ConvertArguments(constructor, encodedConstructor, customSerialization); var instance = constructor.Invoke(arguments); return(instance); }