コード例 #1
0
        /// <summary>
        /// Checks if a constant can be converted from one record data type to another record data type.
        /// </summary>
        /// <param name="newValue">Value to convert.</param>
        /// <param name="oldDataType">Old data type.</param>
        protected virtual void CheckConstantStructuralRecord(Object newValue, StructuralDataType oldDataType)
        {
            var newStructuralType = newValue.TypeSlim as StructuralTypeSlim;

            if (newStructuralType == null || oldDataType.Properties.Count != newStructuralType.Properties.Count)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The number of record entries on '{0}' and '{1}' does not match.", oldDataType, newValue.TypeSlim));
            }

            var oldProperties = oldDataType.Properties;

            if (!Helpers.TryGetStructuralPropertyTypes(newValue.TypeSlim, out var newPropertyTypes))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Cannot convert object of type '{0}' to type '{1}'.", oldDataType.UnderlyingType, newValue.TypeSlim));
            }

            var n = newPropertyTypes.Count;

            for (var i = 0; i < n; i++)
            {
                var oldProperty     = oldProperties[i];
                var newPropertyType = newPropertyTypes[i];

                var oldValue         = oldProperty.GetValue(newValue.Value);
                var newPropertyValue = Object.Create(oldValue, newPropertyType, oldProperty.Type.UnderlyingType);
                CheckConstant(newPropertyValue, oldProperty.Type);
            }
        }
コード例 #2
0
        protected override LambdaExpression VisitStructural(StructuralDataType type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (!_visited.Add(type.UnderlyingType))
            {
                return(Expression.Parameter(typeof(DataTypeBinarySerializer), "serializer").Let(serializerParameter =>
                                                                                                Expression.Parameter(typeof(Stream), "stream").Let(streamParameter =>
                                                                                                                                                   Expression.Lambda(
                                                                                                                                                       Expression.Convert(
                                                                                                                                                           Expression.Call(serializerParameter, ReflectionConstants.Deserialize, Expression.Constant(type.UnderlyingType), streamParameter),
                                                                                                                                                           type.UnderlyingType
                                                                                                                                                           ),
                                                                                                                                                       serializerParameter,
                                                                                                                                                       streamParameter
                                                                                                                                                       )
                                                                                                                                                   )
                                                                                                ));
            }

            try
            {
                return(base.VisitStructural(type));
            }
            finally
            {
                _visited.Remove(type.UnderlyingType);
            }
        }
コード例 #3
0
 protected override LambdaExpression MakeStructural(StructuralDataType type, ReadOnlyCollection <Tuple <DataProperty, LambdaExpression> > properties)
 {
     return(type.StructuralKind switch
     {
         StructuralDataTypeKinds.Anonymous or StructuralDataTypeKinds.Tuple => MakeAnonymousOrTuple(type, properties),
         StructuralDataTypeKinds.Entity or StructuralDataTypeKinds.Record => MakeEntityOrRecord(type, properties),
         _ => throw new NotSupportedException("Only record, anonymous, entity, and tuples are supported structural types."),
     });
コード例 #4
0
        /// <summary>
        /// Checks if a constant can be converted from one tuple data type to another tuple data type.
        /// </summary>
        /// <param name="newValue">Value to convert.</param>
        /// <param name="oldDataType">Old data type.</param>
        protected virtual void CheckConstantStructuralTuple(Object newValue, StructuralDataType oldDataType)
        {
            var newTupleType = newValue.TypeSlim as GenericTypeSlim;

            if (newTupleType == null || oldDataType.Properties.Count != newTupleType.GenericArgumentCount)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The number of tuple components on '{0}' and '{1}' does not match.", oldDataType, newTupleType));
            }

            CheckConstantStructuralByPropertyOrderInstantiation(newValue, oldDataType);
        }
コード例 #5
0
            protected override DataType VisitStructural(StructuralDataType type)
            {
                if (_processed.Add(type.UnderlyingType))
                {
                    if (type.StructuralKind == StructuralDataTypeKinds.Entity)
                    {
                        _enqueue(new KeyValuePair <Type, StructuralDataType>(type.UnderlyingType, type));
                    }

                    return(base.VisitStructural(type));
                }

                return(type);
            }
コード例 #6
0
            protected override void CheckConstantStructuralCore(Object newValue, StructuralDataType oldDataType)
            {
                var oldPropertyMap = oldDataType.Properties.ToDictionary(p => p.Name, p => p);

                var newStructuralType = (StructuralTypeSlim)newValue.TypeSlim;
                var newProperties     = newStructuralType.Properties;

                for (int i = 0, n = newProperties.Count; i < n; i++)
                {
                    var newProperty = newProperties[i];
                    var oldProperty = oldPropertyMap[newProperty.Name];

                    var oldValue         = oldProperty.GetValue(newValue.Value);
                    var newPropertyValue = Object.Create(oldValue, newProperty.PropertyType, oldProperty.Type.UnderlyingType);
                    CheckConstant(newPropertyValue, oldProperty.Type);
                }
            }
コード例 #7
0
        /// <summary>
        /// Converts a constant from one structural data type to another data type.
        /// </summary>
        /// <param name="originalValue">Original value to convert.</param>
        /// <param name="oldDataType">Old data type.</param>
        /// <param name="newDataType">New data type.</param>
        /// <returns>Converted constant.</returns>
        protected virtual object ConvertConstantStructural(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
        {
            if (oldDataType.StructuralKind == newDataType.StructuralKind)
            {
                switch (oldDataType.StructuralKind)
                {
                case StructuralDataTypeKinds.Anonymous:
                    return(ConvertConstantStructuralAnonymous(originalValue, oldDataType, newDataType));

                case StructuralDataTypeKinds.Tuple:
                    return(ConvertConstantStructuralTuple(originalValue, oldDataType, newDataType));

                case StructuralDataTypeKinds.Record:
                    return(ConvertConstantStructuralRecord(originalValue, oldDataType, newDataType));
                }
            }

            return(ConvertConstantStructuralCore(originalValue, oldDataType, newDataType));
        }
コード例 #8
0
        /// <summary>
        /// Checks if a constant can be converted from one structural data type to another data type.
        /// </summary>
        /// <param name="newValue">Value to convert.</param>
        /// <param name="oldDataType">Old data type.</param>
        protected virtual void CheckConstantStructural(Object newValue, StructuralDataType oldDataType)
        {
            switch (oldDataType.StructuralKind)
            {
            case StructuralDataTypeKinds.Anonymous:
                CheckConstantStructuralAnonymous(newValue, oldDataType);
                return;

            case StructuralDataTypeKinds.Tuple:
                CheckConstantStructuralTuple(newValue, oldDataType);
                return;

            case StructuralDataTypeKinds.Record:
                CheckConstantStructuralRecord(newValue, oldDataType);
                return;
            }

            CheckConstantStructuralCore(newValue, oldDataType);
        }
コード例 #9
0
        public void DataTypeVisitor_Change()
        {
            var v = new IncompleteVisitor();

            var d1 = DataType.FromType(typeof(int[]));

            Assert.ThrowsException <NotImplementedException>(() => v.Visit(d1));

            var d2 = DataType.FromType(typeof(bool[]));

            Assert.AreSame(d2, v.Visit(d2));

            var d3 = DataType.FromType(new { a = 1 }.GetType());

            Assert.ThrowsException <NotImplementedException>(() => v.Visit(d3));

            var d4 = DataType.FromType(new { a = true }.GetType());

            Assert.AreSame(d4, v.Visit(d4));

            var d5 = new StructuralDataType(typeof(Foo), new[] { new DataProperty(typeof(Foo).GetField("Bar"), "Bar", DataType.FromType(typeof(int))) }.ToReadOnly(), StructuralDataTypeKinds.Entity);

            Assert.ThrowsException <NotImplementedException>(() => v.Visit(d5));
        }
コード例 #10
0
 protected override object ConvertConstantStructuralCore(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
 {
     throw new NotImplementedException();
 }
コード例 #11
0
            protected override object ConvertConstantStructuralCore(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
            {
                var oldPropertyMap = oldDataType.Properties.ToDictionary(p => p.Name, p => p);

                var newProperties = newDataType.Properties;
                var count         = newProperties.Count;
                var args          = new object[count];

                for (var i = 0; i < count; i++)
                {
                    var newProperty = newProperties[i];
                    var oldProperty = oldPropertyMap[newProperty.Name];

                    var oldValue = oldProperty.GetValue(originalValue);
                    var newValue = ConvertConstant(oldValue, oldProperty.Type, newProperty.Type);

                    args[i] = newValue;
                }

                var res = newDataType.CreateInstance(args);

                return(res);
            }
コード例 #12
0
            protected override object ConvertConstantStructuralCore(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
            {
                var res = newDataType.CreateInstance();

                ConstantsMap[originalValue] = res; // Allow cycles

                var oldPropertyMap = oldDataType.Properties.ToDictionary(p => p.Name, p => p);

                var newProperties = newDataType.Properties;

                for (int i = 0, n = newProperties.Count; i < n; i++)
                {
                    var newProperty = newProperties[i];
                    var oldProperty = oldPropertyMap[newProperty.Name];

                    var oldValue = oldProperty.GetValue(originalValue);
                    var newValue = ConvertConstant(oldValue, oldProperty.Type, newProperty.Type);

                    newProperty.SetValue(res, newValue);
                }

                return(res);
            }
コード例 #13
0
 protected override Type MakeStructural(StructuralDataType type, ReadOnlyCollection <Tuple <string, Type> > properties)
 {
     return(RuntimeCompiler.CreateAnonymousType(properties.Select(p => new KeyValuePair <string, Type>(p.Item1, p.Item2))));
 }
コード例 #14
0
        /// <summary>
        /// Converts a constant from one record data type to another record data type.
        /// </summary>
        /// <param name="originalValue">Original value to convert.</param>
        /// <param name="oldDataType">Old record data type.</param>
        /// <param name="newDataType">New record data type.</param>
        /// <returns>Converted constant.</returns>
        protected virtual object ConvertConstantStructuralRecord(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
        {
            if (oldDataType.Properties.Count != newDataType.Properties.Count)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The number of record entries on '{0}' and '{1}' does not match.", oldDataType, newDataType));
            }

            var oldProperties = oldDataType.Properties;
            var newProperties = newDataType.Properties;

            var result = newDataType.CreateInstance();

            ConstantsMap[originalValue] = result; // Allow cycles

            var n = newProperties.Count;

            for (var i = 0; i < n; i++)
            {
                var oldProperty = oldProperties[i];
                var newProperty = newProperties[i];

                var oldValue = oldProperty.GetValue(originalValue);
                var newValue = ConvertConstant(oldValue, oldProperty.Type, newProperty.Type);

                newProperty.SetValue(result, newValue);
            }

            return(result);
        }
コード例 #15
0
 /// <summary>
 /// Converts a constant from one structural data type to another data type. This method is called when the structural type kind needs to change.
 /// </summary>
 /// <param name="originalValue">Original value to convert.</param>
 /// <param name="oldDataType">Old data type.</param>
 /// <param name="newDataType">New data type.</param>
 /// <returns>Converted constant.</returns>
 protected abstract object ConvertConstantStructuralCore(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType);
コード例 #16
0
        /// <summary>
        /// Converts a constant from one tuple data type to another tuple data type.
        /// </summary>
        /// <param name="originalValue">Original value to convert.</param>
        /// <param name="oldDataType">Old tuple data type.</param>
        /// <param name="newDataType">New tuple data type.</param>
        /// <returns>Converted constant.</returns>
        protected virtual object ConvertConstantStructuralTuple(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
        {
            if (oldDataType.Properties.Count != newDataType.Properties.Count)
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "The number of tuple components on '{0}' and '{1}' does not match.", oldDataType, newDataType));
            }

            return(ConvertConstantStructuralByPropertyOrderInstantiation(originalValue, oldDataType, newDataType));
        }
コード例 #17
0
        /// <summary>
        /// Converts a constant by instantiating the new data type based on the converted values of the original data type's properties, in declaration order.
        /// </summary>
        /// <param name="originalValue">Original value to convert.</param>
        /// <param name="oldDataType">Old data type.</param>
        /// <param name="newDataType">New data type.</param>
        /// <returns>Converted constant.</returns>
        /// <remarks>Anonymous types and tuple data types obey to the prerequisite of property ordering according to the constructor parameter list.</remarks>
        protected object ConvertConstantStructuralByPropertyOrderInstantiation(object originalValue, StructuralDataType oldDataType, StructuralDataType newDataType)
        {
            var oldProperties = oldDataType.Properties;
            var newProperties = newDataType.Properties;

            var n    = newProperties.Count;
            var args = new object[n];

            for (var i = 0; i < n; i++)
            {
                var oldProperty = oldProperties[i];
                var newProperty = newProperties[i];

                var oldValue = oldProperty.GetValue(originalValue);
                var newValue = ConvertConstant(oldValue, oldProperty.Type, newProperty.Type);

                args[i] = newValue;
            }

            var result = newDataType.CreateInstance(args);

            return(result);
        }
コード例 #18
0
        /// <summary>
        /// Visit new expressions for structural data types and transforms occurrences of entity types.
        /// </summary>
        /// <param name="node">The expression to transform.</param>
        /// <param name="oldType">The original type of the new expression.</param>
        /// <param name="newDataType">The new data type of the new expression.</param>
        /// <returns>The new expression with the original type replaced with the new type.</returns>
        protected virtual Expression VisitNewStructuralDataType(NewExpression node, Type oldType, StructuralDataType newDataType)
        {
            var newType = newDataType.UnderlyingType;

            var oldConstructor = node.Constructor;
            var oldParameters  = oldConstructor.GetParameters();
            var count          = oldParameters.Length;
            var oldArguments   = node.Arguments;

            var memberAssignments = new Dictionary <MemberInfo, Expression>(count);

            for (var i = 0; i < count; i++)
            {
                var oldParameter = oldParameters[i];
                var oldArgument  = oldArguments[i];

                var mapping = oldParameter.GetCustomAttribute <MappingAttribute>(inherit: false);
                Debug.Assert(mapping != null);

                var newProperty = newType.GetProperty(mapping.Uri);
                Debug.Assert(newProperty != null);

                if (memberAssignments.ContainsKey(newProperty))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Parameter '{0}' on the constructor of '{1}' has the same mapping attribute '{2}' of another parameter.", oldParameter.Name, oldType, mapping.Uri));
                }

                var newArgument = Visit(oldArgument);
                memberAssignments[newProperty] = newArgument;
            }

            return(CreateNewExpression(newType, memberAssignments));
        }
コード例 #19
0
 /// <summary>
 /// Checks if a constant can be converted from one structural data type to another data type. This method is called when the structural type kind needs to change.
 /// </summary>
 /// <param name="newValue">Value to convert.</param>
 /// <param name="oldDataType">Old data type.</param>
 protected abstract void CheckConstantStructuralCore(Object newValue, StructuralDataType oldDataType);
コード例 #20
0
        /// <summary>
        /// Visit member initializer expressions for structural data types and transforms occurrences of entity types.
        /// </summary>
        /// <param name="node">The expression to transform.</param>
        /// <param name="oldType">The original type of the member initializer expression.</param>
        /// <param name="newDataType">The new data type of the member initializer expression.</param>
        /// <returns>The member initializer expression with the original type replaced with the new type.</returns>
        protected virtual Expression VisitMemberInitStructuralDataType(MemberInitExpression node, Type oldType, StructuralDataType newDataType)
        {
            var newType = newDataType.UnderlyingType;

            var memberAssignments = default(IDictionary <MemberInfo, Expression>);

            var newExpression = Visit(node.NewExpression);

            switch (newExpression.NodeType)
            {
            case ExpressionType.MemberInit:
                memberAssignments = GetMemberAssignments((MemberInitExpression)newExpression);
                break;

            case ExpressionType.New:
                memberAssignments = GetMemberAssignments((NewExpression)newExpression);
                break;
            }

            return(CreateNewExpressionFromBindings(newType, node.Bindings, memberAssignments));
        }
コード例 #21
0
        /// <summary>
        /// Checks if a constant can be converted based on the converted values of the original data type's properties, in declaration order.
        /// </summary>
        /// <param name="newValue">Value to convert.</param>
        /// <param name="oldDataType">Old data type.</param>
        /// <remarks>Anonymous types and tuple data types obey to the prerequisite of property ordering according to the constructor parameter list.</remarks>
        protected void CheckConstantStructuralByPropertyOrderInstantiation(Object newValue, StructuralDataType oldDataType)
        {
            var oldProperties = oldDataType.Properties;

            if (!Helpers.TryGetStructuralPropertyTypes(newValue.TypeSlim, out var newPropertyTypes))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Cannot convert object of type '{0}' to type '{1}'.", oldDataType.UnderlyingType, newValue.TypeSlim));
            }

            var n = newPropertyTypes.Count;

            for (var i = 0; i < n; i++)
            {
                var oldProperty     = oldProperties[i];
                var newPropertyType = newPropertyTypes[i];

                var oldValue         = oldProperty.GetValue(newValue.Value);
                var newPropertyValue = Object.Create(oldValue, newPropertyType, oldProperty.Type.UnderlyingType);
                CheckConstant(newPropertyValue, oldProperty.Type);
            }
        }
コード例 #22
0
 protected override DataType VisitStructural(StructuralDataType type)
 {
     _assertStructural(type.UnderlyingType);
     return(base.VisitStructural(type));
 }