Exemplo n.º 1
0
        private static bool LinkDecoder <T>(IDecoderDescriptor <T> descriptor, BindingFlags bindings,
                                            IDictionary <Type, object> parents)
        {
            var entityType = typeof(T);

            parents[entityType] = descriptor;

            if (Linker.TryLinkDecoderAsValue(descriptor))
            {
                return(true);
            }

            // Bind descriptor as an array of target type is also array
            if (entityType.IsArray)
            {
                var element = entityType.GetElementType();
                var setter  = MethodResolver
                              .Create <Func <Setter <object[], IEnumerable <object> > > >(() =>
                                                                                          SetterGenerator.CreateFromEnumerable <object>())
                              .SetGenericArguments(element)
                              .Invoke(null);

                return(Linker.LinkDecoderAsArray(descriptor, bindings, element, setter, parents));
            }

            // Try to bind descriptor as an array if target type IEnumerable<>
            foreach (var interfaceType in entityType.GetInterfaces())
            {
                // Make sure that interface is IEnumerable<T> and store typeof(T)
                if (!TypeResolver.Create(interfaceType)
                    .HasSameDefinitionThan <IEnumerable <object> >(out var interfaceTypeArguments))
                {
                    continue;
                }

                var elementType = interfaceTypeArguments[0];

                // Search constructor compatible with IEnumerable<>
                foreach (var constructor in entityType.GetConstructors())
                {
                    var parameters = constructor.GetParameters();

                    if (parameters.Length != 1)
                    {
                        continue;
                    }

                    var parameterType = parameters[0].ParameterType;

                    if (!TypeResolver.Create(parameterType)
                        .HasSameDefinitionThan <IEnumerable <object> >(out var parameterArguments) ||
                        parameterArguments[0] != elementType)
                    {
                        continue;
                    }

                    var setter = MethodResolver
                                 .Create <Func <ConstructorInfo, Setter <object, object> > >(c =>
                                                                                             SetterGenerator.CreateFromConstructor <object, object>(c))
                                 .SetGenericArguments(entityType, parameterType)
                                 .Invoke(null, constructor);

                    return(Linker.LinkDecoderAsArray(descriptor, bindings, elementType, setter, parents));
                }
            }

            // Bind readable and writable instance properties
            foreach (var property in entityType.GetProperties(bindings))
            {
                if (property.GetGetMethod() == null || property.GetSetMethod() == null ||
                    property.Attributes.HasFlag(PropertyAttributes.SpecialName))
                {
                    continue;
                }

                var setter = MethodResolver
                             .Create <Func <PropertyInfo, Setter <object, object> > >(p =>
                                                                                      SetterGenerator.CreateFromProperty <object, object>(p))
                             .SetGenericArguments(entityType, property.PropertyType)
                             .Invoke(null, property);

                if (!Linker.LinkDecoderAsObject(descriptor, bindings, property.PropertyType, property.Name, setter,
                                                parents))
                {
                    return(false);
                }
            }

            // Bind public instance fields
            foreach (var field in entityType.GetFields(bindings))
            {
                if (field.Attributes.HasFlag(FieldAttributes.SpecialName))
                {
                    continue;
                }

                var setter = MethodResolver
                             .Create <Func <FieldInfo, Setter <object, object> > >(f =>
                                                                                   SetterGenerator.CreateFromField <object, object>(f))
                             .SetGenericArguments(entityType, field.FieldType)
                             .Invoke(null, field);

                if (!Linker.LinkDecoderAsObject(descriptor, bindings, field.FieldType, field.Name, setter, parents))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Describe and create encoder for given schema using reflection on target entity. Only public instance fields
 /// and properties are linked.
 /// </summary>
 /// <typeparam name="TEntity">Entity type</typeparam>
 /// <param name="schema">Entity schema</param>
 /// <returns>Entity encoder</returns>
 public static IEncoder <TEntity> CreateEncoder <TEntity>(ISchema <TEntity> schema)
 {
     return(Linker.CreateEncoder(schema, Linker.DefaultBindings));
 }
Exemplo n.º 3
0
        private static bool LinkDecoderAsObject <TEntity>(IDecoderDescriptor <TEntity> descriptor, BindingFlags bindings,
                                                          Type type, string name, object setter, IDictionary <Type, object> parents)
        {
            var constructor = MethodResolver
                              .Create <Func <object> >(() => ConstructorGenerator.CreateConstructor <object>())
                              .SetGenericArguments(type)
                              .Invoke(null);

            if (parents.TryGetValue(type, out var parent))
            {
                MethodResolver
                .Create <Func <IDecoderDescriptor <TEntity>, string, Func <object>, Setter <TEntity, object>,
                               IDecoderDescriptor <object>, IDecoderDescriptor <object> > >((d, n, c, s, p) =>
                                                                                            d.HasField(n, c, s, p))
                .SetGenericArguments(type)
                .Invoke(descriptor, name, constructor, setter, parent);

                return(true);
            }

            var fieldDescriptor = MethodResolver
                                  .Create <Func <IDecoderDescriptor <TEntity>, string, Func <object>, Setter <TEntity, object>,
                                                 IDecoderDescriptor <object> > >((d, n, c, s) => d.HasField(n, c, s))
                                  .SetGenericArguments(type)
                                  .Invoke(descriptor, name, constructor, setter);

            var result = MethodResolver
                         .Create <Func <IDecoderDescriptor <object>, BindingFlags, Dictionary <Type, object>, bool> >((d, f, p) =>
                                                                                                                      Linker.LinkDecoder(d, f, p))
                         .SetGenericArguments(type)
                         .Invoke(null, fieldDescriptor, bindings, parents);

            return(result is bool success && success);
        }
Exemplo n.º 4
0
        private static bool LinkEncoderAsObject <TEntity>(IEncoderDescriptor <TEntity> descriptor, BindingFlags bindings,
                                                          Type type, string name, object getter, IDictionary <Type, object> parents)
        {
            if (parents.TryGetValue(type, out var recurse))
            {
                MethodResolver
                .Create <Func <IEncoderDescriptor <TEntity>, string, Func <TEntity, object>, IEncoderDescriptor <object>,
                               IEncoderDescriptor <object> > >((d, n, a, p) => d.HasField(n, a, p))
                .SetGenericArguments(type)
                .Invoke(descriptor, name, getter, recurse);

                return(true);
            }

            var fieldDescriptor = MethodResolver
                                  .Create <Func <IEncoderDescriptor <TEntity>, string, Func <TEntity, object>, IEncoderDescriptor <object> > >(
                (d, n, a) => d.HasField(n, a))
                                  .SetGenericArguments(type)
                                  .Invoke(descriptor, name, getter);

            var result = MethodResolver
                         .Create <Func <IEncoderDescriptor <object>, BindingFlags, Dictionary <Type, object>, bool> >((d, f, p) =>
                                                                                                                      Linker.LinkEncoder(d, f, p))
                         .SetGenericArguments(type)
                         .Invoke(null, fieldDescriptor, bindings, parents);

            return(result is bool success && success);
        }
Exemplo n.º 5
0
        private static bool LinkDecoderAsArray <TEntity>(IDecoderDescriptor <TEntity> descriptor, BindingFlags bindings,
                                                         Type type, object setter, IDictionary <Type, object> parents)
        {
            var constructor = MethodResolver
                              .Create <Func <object> >(() => ConstructorGenerator.CreateConstructor <object>())
                              .SetGenericArguments(type)
                              .Invoke(null);

            if (parents.TryGetValue(type, out var recurse))
            {
                MethodResolver
                .Create <Func <IDecoderDescriptor <TEntity>, Func <object>, Setter <TEntity, IEnumerable <object> >,
                               IDecoderDescriptor <object>, IDecoderDescriptor <object> > >((d, c, s, p) => d.HasElements(c, s, p))
                .SetGenericArguments(type)
                .Invoke(descriptor, constructor, setter, recurse);

                return(true);
            }

            var itemDescriptor = MethodResolver
                                 .Create <Func <IDecoderDescriptor <TEntity>, Func <object>, Setter <TEntity, IEnumerable <object> >,
                                                IDecoderDescriptor <object> > >((d, c, s) => d.HasElements(c, s))
                                 .SetGenericArguments(type)
                                 .Invoke(descriptor, constructor, setter);

            var result = MethodResolver
                         .Create <Func <IDecoderDescriptor <object>, BindingFlags, Dictionary <Type, object>, bool> >((d, f, p) =>
                                                                                                                      Linker.LinkDecoder(d, f, p))
                         .SetGenericArguments(type)
                         .Invoke(null, itemDescriptor, bindings, parents);

            return(result is bool success && success);
        }