/// <summary> /// Describe and create decoder for given schema using reflection on target entity and provided binding flags. /// </summary> /// <typeparam name="TEntity">Entity type</typeparam> /// <param name="schema">Entity schema</param> /// <param name="bindings">Binding flags used to filter bound fields and properties</param> /// <returns>Entity decoder</returns> public static IDecoder <TEntity> CreateDecoder <TEntity>(ISchema <TEntity> schema, BindingFlags bindings) { if (!Linker.LinkDecoder(schema.DecoderDescriptor, bindings, new Dictionary <Type, object>())) { throw new ArgumentException($"can't link decoder for type '{typeof(TEntity)}'", nameof(schema)); } return(schema.CreateDecoder(ConstructorGenerator.CreateConstructor <TEntity>())); }
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); }
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); }