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); }
public IEncoderDescriptor <TElement> HasElements <TElement>(Func <TEntity, IEnumerable <TElement> > getter, IEncoderDescriptor <TElement> descriptor) { if (!(descriptor is TreeEncoderDescriptor <TState, TNative, TElement> ancestor)) { throw new ArgumentOutOfRangeException(nameof(descriptor), "incompatible descriptor type"); } return(TreeEncoderDescriptor <TState, TNative, TEntity> .BindArray(this.definition, getter, ancestor)); }
public IEncoderDescriptor <TField> HasField <TField>(string name, Func <TEntity, TField> getter, IEncoderDescriptor <TField> descriptor) { if (!(descriptor is TreeEncoderDescriptor <TState, TNative, TField> ancestor)) { throw new ArgumentOutOfRangeException(nameof(descriptor), "incompatible descriptor type"); } return(TreeEncoderDescriptor <TState, TNative, TEntity> .BindField(this.definition, name, this.fields, getter, ancestor)); }
private static bool TryLinkEncoderAsValue <TEntity>(IEncoderDescriptor <TEntity> descriptor) { try { descriptor.HasValue(); return(true); } catch (InvalidCastException) { // Invalid cast exception being thrown means binding fails return(false); } }
private static bool LinkEncoder <T>(IEncoderDescriptor <T> descriptor, BindingFlags bindings, IDictionary <Type, object> parents) { var entityType = typeof(T); parents[entityType] = descriptor; if (Linker.TryLinkEncoderAsValue(descriptor)) { return(true); } // Bind descriptor as an array of target type is also array if (entityType.IsArray) { var element = entityType.GetElementType(); var getter = MethodResolver .Create <Func <Func <object, object> > >(() => GetterGenerator.CreateIdentity <object>()) .SetGenericArguments(typeof(IEnumerable <>).MakeGenericType(element)) .Invoke(null); return(Linker.LinkEncoderAsArray(descriptor, bindings, element, getter, 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 arguments)) { continue; } var elementType = arguments[0]; var getter = MethodResolver .Create <Func <Func <object, object> > >(() => GetterGenerator.CreateIdentity <object>()) .SetGenericArguments(typeof(IEnumerable <>).MakeGenericType(elementType)) .Invoke(null); return(Linker.LinkEncoderAsArray(descriptor, bindings, elementType, getter, 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 getter = MethodResolver .Create <Func <PropertyInfo, Func <object, object> > >(p => GetterGenerator.CreateFromProperty <object, object>(p)) .SetGenericArguments(entityType, property.PropertyType) .Invoke(null, property); if (!Linker.LinkEncoderAsObject(descriptor, bindings, property.PropertyType, property.Name, getter, parents)) { return(false); } } // Bind public instance fields foreach (var field in entityType.GetFields(bindings)) { if (field.Attributes.HasFlag(FieldAttributes.SpecialName)) { continue; } var getter = MethodResolver .Create <Func <FieldInfo, Func <object, object> > >(f => GetterGenerator.CreateFromField <object, object>(f)) .SetGenericArguments(entityType, field.FieldType) .Invoke(null, field); if (!Linker.LinkEncoderAsObject(descriptor, bindings, field.FieldType, field.Name, getter, parents)) { return(false); } } return(true); }