コード例 #1
0
        internal static object CreateDeserializationTarget(Type objectType, out IValueContainer valueContainer)
        {
            if (objectType == null || objectType == typeof(IValueContainer))
            {
                valueContainer = new ValueContainer.ValueContainer();
                return(valueContainer);
            }

            object target = Activator.CreateInstance(objectType);

            if (typeof(IValueContainer).IsAssignableFrom(objectType))
            {
                valueContainer = (IValueContainer)target;
            }
            else
            {
                valueContainer = ValueContainerFactory.CreateProxy(target);
            }

            return(target);
        }
コード例 #2
0
        public void OnValueEnd()
        {
            if (_scope.ParentScope != null &&
                _scope.ParentScope.Composer == null &&
                _scope.ParentScope.Container == null)
            {
                _scope.ParentScope.IsDynamicContainer = true;
            }

            if (!_scope.ValueReceived && _scope.Composer != null)
            {
                _scope.Value         = _scope.Composer.Compose(_scope.Container, _scope.Type);
                _scope.ValueReceived = true;
            }

            if (!_scope.ValueReceived && _scope.IsDynamicContainer)
            {
                _scope.Value         = _scope.Container;
                _scope.ValueReceived = true;
            }

            if (!_scope.ValueReceived && !_scope.ValueInfo.IsCollection && _scope.Container == null)
            {
                if (_scope.ValueInfo.ReferenceId.HasValue)
                {
                    if (!_objectByIdMap.TryGetValue(_scope.ValueInfo.ReferenceId.Value, out _scope.Value))
                    {
                        throw new InvalidOperationException($"Could not find object by ID '{_scope.ValueInfo.ReferenceId.Value}'.");
                    }
                    _scope.ValueReceived = true;
                }
                else if (_scope.ValueInfo.SpecialId != null)
                {
                    if (_objectByNameMap == null || !_objectByNameMap.TryGetValue(_scope.ValueInfo.SpecialId, out _scope.Value))
                    {
                        throw new InvalidOperationException($"Could not find object by ID '{_scope.ValueInfo.SpecialId}'.");
                    }
                    _scope.ValueReceived = true;
                }
            }

            var valueScope = _scope;

            _scope = _scope.ParentScope;

            if (valueScope.ValueReceived && _scope != null)
            {
                var value = valueScope.Value;

#warning Support various collection types. Currently supports arrays only.
                if (valueScope.ValueInfo.IsCollection)
                {
                    value = this.GetType()
                            .GetMethod(nameof(ToArray), BindingFlags.Static | BindingFlags.NonPublic)
                            .MakeGenericMethod(value.GetType().GetGenericArguments()[0])
                            .Invoke(null, new object[] { value });
                }

                Type targetType;
                if (_scope.ValueInfo.IsCollection)
                {
                    targetType = _scope.ItemType;
                }
                else if (_scope.IsDynamicContainer)
                {
                    targetType = value?.GetType();
                }
                else
                {
                    var startIndex = _scope.Index + 1;

                    _scope.Index = FindIndex(_scope.Container, valueScope.ValueInfo.Name, startIndex);

                    // Try to find by value type if the argument was renamed.
                    if (_scope.Index < 0 && value != null)
                    {
                        _scope.Index = FindIndex(_scope.Container, value.GetType());
                    }

                    if (_scope.Index >= 0)
                    {
                        targetType = _scope.Container.GetType(_scope.Index);
                    }
                    else
                    {
                        // TODO: better skip logic?
                        value        = null;
                        targetType   = null;
                        _scope.Index = startIndex - 1;
                    }
                }

                if (value != null && targetType != null)
                {
                    value = EnsureValueType(targetType, value);

                    if (valueScope.ValueInfo.ReferenceId.HasValue)
                    {
                        _objectByIdMap[valueScope.ValueInfo.ReferenceId.Value] = value;
                    }

                    if (_scope.ValueInfo.IsCollection)
                    {
                        _scope.Array.Add(value);
                    }
                    else if (_scope.IsDynamicContainer)
                    {
                        var dynamicContainer = _scope.Container as ValueContainer.ValueContainer;
                        if (dynamicContainer == null)
                        {
                            dynamicContainer = new ValueContainer.ValueContainer();
                            _scope.Container = dynamicContainer;
                        }
                        dynamicContainer.Add(valueScope.ValueInfo.Name, targetType, value);
                    }
                    else
                    {
                        _scope.Container.SetValue(_scope.Index, value);
                    }
                }
            }
        }
コード例 #3
0
ファイル: ObjectReconstructor.cs プロジェクト: anhzin/Dasync
        public void OnValueEnd()
        {
            if (_scope.ParentScope != null &&
                _scope.ParentScope.Composer == null &&
                _scope.ParentScope.Container == null)
            {
                _scope.ParentScope.IsDynamicContainer = true;
            }

            if (!_scope.ValueReceived && _scope.Composer != null)
            {
                _scope.Value         = _scope.Composer.Compose(_scope.Container, _scope.Type);
                _scope.ValueReceived = true;
            }

            if (!_scope.ValueReceived && _scope.IsDynamicContainer)
            {
                _scope.Value         = _scope.Container;
                _scope.ValueReceived = true;
            }

            if (!_scope.ValueReceived)
            {
                if (_scope.ValueInfo.ReferenceId.HasValue)
                {
                    if (!_objectByIdMap.TryGetValue(_scope.ValueInfo.ReferenceId.Value, out _scope.Value))
                    {
                        throw new InvalidOperationException($"Could not find object by ID '{_scope.ValueInfo.ReferenceId.Value}'.");
                    }
                    _scope.ValueReceived = true;
                }
                else if (_scope.ValueInfo.SpecialId != null)
                {
                    if (_objectByNameMap == null || !_objectByNameMap.TryGetValue(_scope.ValueInfo.SpecialId, out _scope.Value))
                    {
                        throw new InvalidOperationException($"Could not find object by ID '{_scope.ValueInfo.SpecialId}'.");
                    }
                    _scope.ValueReceived = true;
                }
            }

            var valueScope = _scope;

            _scope = _scope.ParentScope;

            if (valueScope.ValueReceived)
            {
                var value = valueScope.Value;

#warning Support various collection types. Currently supports arrays only.
                if (valueScope.ValueInfo.IsCollection)
                {
                    value = this.GetType()
                            .GetMethod(nameof(ToArray), BindingFlags.Static | BindingFlags.NonPublic)
                            .MakeGenericMethod(value.GetType().GetGenericArguments()[0])
                            .Invoke(null, new object[] { value });
                }

                Type targetType;
                if (_scope.ValueInfo.IsCollection)
                {
                    targetType = _scope.ItemType;
                }
                else if (_scope.IsDynamicContainer)
                {
                    targetType = value?.GetType();
                }
                else
                {
                    _scope.Index = FindIndex(_scope.Container, valueScope.ValueInfo.Name, _scope.Index + 1);
                    if (_scope.Index >= 0)
                    {
                        targetType = _scope.Container.GetType(_scope.Index);
                    }
                    else
                    {
                        // TODO: better skip logic?
                        value      = null;
                        targetType = null;
                    }
                }

                if (value != null && targetType != null)
                {
                    // TODO: converter
                    if (!targetType.IsAssignableFrom(value.GetType()))
                    {
                        if (targetType.IsArray || ((value is IList) && targetType == typeof(object)))
                        {
#warning This byte[] conversion is a quick-fix. Do it properly by adding type during serialization?
                            if (targetType == typeof(byte[]) && value is string)
                            {
                                value = Convert.FromBase64String((string)value);
                            }
                            else
                            {
                                value = this.GetType()
                                        .GetMethod(nameof(ToArray), BindingFlags.Static | BindingFlags.NonPublic)
                                        .MakeGenericMethod(targetType.GetElementType() ?? value.GetType().GetGenericArguments()[0])
                                        .Invoke(null, new object[] { value });
                            }
                        }
                        else if (targetType.IsEnum())
                        {
                            value = Enum.ToObject(targetType, value);
                        }
                        else if (targetType == typeof(Guid) && value is string strGuid)
                        {
                            value = Guid.Parse(strGuid);
                        }
                        else if (targetType is Type && value is TypeSerializationInfo typeInfo)
                        {
                            value = ResolveType(typeInfo);
                        }
                        else
                        {
                            value = Convert.ChangeType(value, targetType);
                        }
                    }

                    if (valueScope.ValueInfo.ReferenceId.HasValue)
                    {
                        _objectByIdMap[valueScope.ValueInfo.ReferenceId.Value] = value;
                    }

                    if (_scope.ValueInfo.IsCollection)
                    {
                        _scope.Array.Add(value);
                    }
                    else if (_scope.IsDynamicContainer)
                    {
                        var dynamicContainer = _scope.Container as ValueContainer.ValueContainer;
                        if (dynamicContainer == null)
                        {
                            dynamicContainer = new ValueContainer.ValueContainer();
                            _scope.Container = dynamicContainer;
                        }
                        dynamicContainer.Add(valueScope.ValueInfo.Name, targetType, value);
                    }
                    else
                    {
                        _scope.Container.SetValue(_scope.Index, value);
                    }
                }
            }
        }