Beispiel #1
0
        public static bool FeatureEnabled <TFeature, TOptions>(this IServiceProvider serviceProvider,
                                                               out TFeature feature)
            where TFeature : class, IFeatureToggle
            where TOptions : class, new()
        {
            var options = serviceProvider.GetService(typeof(IOptionsMonitor <TOptions>));

            if (!(options is IOptionsMonitor <TOptions> o))
            {
                feature = default;
                return(false);
            }

            var type        = o.CurrentValue.GetType();
            var members     = AccessorMembers.Create(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public);
            var featureType = members.SingleOrDefault(x => x.Type == typeof(TFeature));

            if (featureType == null)
            {
                feature = default;
                return(false);
            }

            var accessor = ReadAccessor.Create(type);

            feature = accessor[o.CurrentValue, featureType.Name] as TFeature;
            return(feature != null && feature.Enabled);
        }
Beispiel #2
0
        public Type GetTypeFor(object instance)
        {
            var baseType = instance.GetType();
            var members  = AccessorMembers.Create(baseType, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            if (!members.TryGetValue("Type", out _))
            {
                return(baseType);                // no type discriminator
            }
            if (!IsTypeDiscriminated(baseType, out var subTypes))
            {
                return(baseType);                // no matching subTypes
            }
            var read    = ReadAccessor.Create(instance, AccessorMemberTypes.Properties, AccessorMemberScope.Public);
            var typeKey = read[instance, "Type"]?.ToString();

            if (string.IsNullOrWhiteSpace(typeKey))
            {
                return(baseType);                // missing type discriminant
            }
            var subType = subTypes.SingleOrDefault(x => x.Name == typeKey) ??
                          subTypes.SingleOrDefault(x => x.Name == $"{typeKey}{baseType.Name}");

            if (subType == null)
            {
                return(baseType);                // sub-type error
            }
            return(subType);
        }
Beispiel #3
0
        public static List <Error> MustExistOnType <T>(FuncEnumerable <T, string> fields)
        {
            var type = typeof(T);
            var list = new List <Error>();

            foreach (var field in fields)
            {
                var valid = false;
                foreach (var member in AccessorMembers.Create(type))
                {
                    if (field.Equals(member.Name, StringComparison.OrdinalIgnoreCase))
                    {
                        valid = true;
                    }
                }
                if (!valid)
                {
                    list.Add(new Error(ErrorEvents.FieldDoesNotMatch,
                                       string.Format(ErrorStrings.FieldToPropertyMismatch, field, type.Name),
                                       HttpStatusCode.BadRequest));
                }
            }

            return(list);
        }
        public static string GetHeaderText <TMetadata>(string separator)
        {
            return(Pooling.StringBuilderPool.Scoped(sb =>
            {
                var members = AccessorMembers.Create(typeof(TMetadata), AccessorMemberTypes.Fields,
                                                     AccessorMemberScope.Public);

                // FIXME: convert to zero-alloc
                var columns = members
                              .Where(x => x.HasAttribute <ColumnAttribute>())
                              .OrderBy(x => x.TryGetAttribute(out ColumnAttribute column) ? -1 : column.Order)
                              .ToArray();

                var i = 0;
                foreach (var member in columns)
                {
                    member.TryGetAttribute(out ColumnAttribute column);
                    member.TryGetAttribute(out DisplayAttribute display);
                    var name = display?.Name ?? column.Name ?? member.Name;
                    sb.Append(name);

                    i++;
                    if (i < columns.Length)
                    {
                        sb.Append(separator);
                    }
                }
            }));
        }
Beispiel #5
0
        public override async Task OnValidRequestAsync(Type underlyingType, StringValues clauses, ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var members = AccessorMembers.Create(underlyingType, AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                                 AccessorMemberScope.Public);

            // FIXME: add attribute for model ID discriminator, or fail due to missing "Id"
            if (!members.TryGetValue("Id", out _))
            {
                _logger.LogWarning(_localizer.GetString("Sorting operation was skipped, because the underlying resource does not have an 'Id' property."));
                await next.Invoke();

                return;
            }

            // FIXME: avoid allocation here?
            var sortMap = new List <(AccessorMember, SortDirection)>(clauses.Count);

            foreach (var value in clauses)
            {
                var tokens = value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
                if (tokens.Length == 0)
                {
                    continue; // (FIXME: add a validation error?)
                }
                var clause = tokens[0];
                var name   = clause[(clause.IndexOf('=', StringComparison.Ordinal) + 1)..];
Beispiel #6
0
        public void Apply(OpenApiSchema schema, SchemaFilterContext context)
        {
            DocumentXmlSchemas(schema, context);

            if (!typeof(IResource).IsAssignableFrom(context.Type))
            {
                return;
            }

            foreach (var member in AccessorMembers.Create(context.Type, AccessorMemberTypes.Properties, AccessorMemberScope.Public))
            {
                if (!member.TryGetAttribute <ProtectedByPolicyAttribute>(out var attribute))
                {
                    continue;
                }

                var user = _http.ResolveCurrentPrincipal();
                if (!user.Claims.Any() || !_authorization.AuthorizeAsync(user, null, attribute.PolicyName)
                    .ConfigureAwait(false).GetAwaiter().GetResult().Succeeded)
                {
                    var propertyName = char.ToLowerInvariant(member.Name[0]) + member.Name.Substring(1);
                    schema.Properties.Remove(propertyName);
                }
            }

            if (_builder.TryGetResourceNameForType(context.Type, out var name))
            {
                schema.Title = name;
            }
        }
Beispiel #7
0
        public static bool FeatureEnabled <TFeature, TOptions>(this IServiceProvider serviceProvider,
                                                               out TFeature feature)
            where TFeature : FeatureToggle where TOptions : class, new()
        {
            var options = serviceProvider.GetService(typeof(IOptions <TOptions>));

            if (!(options is IOptions <TOptions> o))
            {
                feature = default;
                return(false);
            }

            var featureType = AccessorMembers.Create(o.Value.GetType()).SingleOrDefault(x => x.Type == typeof(TFeature));

            if (featureType == null)
            {
                feature = default;
                return(false);
            }

            var accessor = ReadAccessor.Create(featureType.Type);

            feature = accessor[o.Value, featureType.Name] as TFeature;
            return(feature != null && feature.Enabled);
        }
Beispiel #8
0
        public async Task <Operation <ulong> > CountAsync(Type type, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var members = AccessorMembers.Create(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            return(await members.CountAsync(_dialect, _connectionString, cancellationToken));
        }
Beispiel #9
0
 public Prototype(TInterface parent, object child)
 {
     _parent      = parent;
     _child       = child;
     _memberNames =
         AccessorMembers.Create(typeof(TInterface)).Select(x => x.Name)
         .Concat(typeof(TInterface).GetMethods().Select(x => x.Name))
         .ToImmutableHashSet();
 }
Beispiel #10
0
        private static ResourceQuery DeserializeResourceQuery(byte[] buffer)
        {
            var query = new ResourceQuery();

            var ms = new MemoryStream(buffer);
            var br = new BinaryReader(ms);

            query.PageOffset  = br.ReadNullableInt32();
            query.PageSize    = br.ReadNullableInt32();
            query.MaxPageSize = br.ReadNullableInt32();

            query.CountTotalRows = br.ReadBoolean();
            query.TotalRows      = br.ReadNullableInt32();

            if (br.ReadBoolean())
            {
                var fields = br.ReadInt32();
                query.Fields = new List <string>(fields);
                for (var i = 0; i < fields; i++)
                {
                    query.Fields.Add(br.ReadString());
                }
            }

            if (br.ReadBoolean())
            {
                var sorts = br.ReadInt32();
                query.Sorting = new List <(AccessorMember, SortDirection)>(sorts);
                for (var i = 0; i < sorts; i++)
                {
                    var declaringTypeName = br.ReadNullableString();
                    if (declaringTypeName != null)
                    {
                        var declaringType = Type.GetType(declaringTypeName);
                        var memberName    = br.ReadString();
                        var direction     = (SortDirection)br.ReadByte();

                        if (declaringType == null)
                        {
                            continue;
                        }

                        var members = AccessorMembers.Create(declaringType, AccessorMemberTypes.Properties,
                                                             AccessorMemberScope.Public);

                        if (members.TryGetValue(memberName, out var member))
                        {
                            query.Sorting.Add((member, direction));
                        }
                    }
                }
            }

            return(query);
        }
        public static IEnumerable <T> StreamFrame <T>(string filePath, bool reuseRowObject = false) where T : class, new()
        {
            // We need to be explicit here because the CSV reader will guess at primitives like `float` when `double` is defined in the mode.
            var members = AccessorMembers.Create(typeof(T), AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                                 AccessorMemberScope.Public);
            var inputFrame = DataFrame.ReadCsv(filePath, columnNames: members.Names.ToArray(),
                                               dataTypes: members.Select(x => x.Type).ToArray());
            var context    = new MLContext();
            var enumerable = context.Data.CreateEnumerable <T>(inputFrame, reuseRowObject);

            return(enumerable);
        }
Beispiel #12
0
        public PropertyAccessor(ITypeReadAccessor reads, ITypeWriteAccessor writes, string name)
        {
            var members = AccessorMembers.Create(reads.Type, AccessorMemberTypes.Properties);

            Info = members.PropertyInfo.Single(m => m.Name == name);

            Type = Info.PropertyType;
            Name = name;

            _reads  = reads;
            _writes = writes;
        }
Beispiel #13
0
        public static async Task <Operation <TShape> > QueryOneByExampleAsync <TShape>(this ISqlDialect dialect, object example, Func <ISqlDialect, string, IReadOnlyDictionary <string, object>, CancellationToken, Task <TShape> > queryFunc, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var members = AccessorMembers.Create(example, AccessorMemberTypes.Properties, AccessorMemberScope.Public);
            var hash    = members.ToHash(example);

            var sql        = dialect.Select(members, hash);
            var parameters = hash.ToDictionary(k => $"{dialect.Parameter}{dialect.ResolveColumnName(k.Key)}", v => hash[v.Key]);

            var result = await queryFunc(dialect, sql, parameters, cancellationToken);

            return(new Operation <TShape> {
                Data = result
            });
        }
        static JsonDeltaConverter()
        {
            var delta = AccessorMembers.Create(typeof(DeltaAnnotated <T>), AccessorMemberTypes.Properties,
                                               AccessorMemberScope.Public) ?? throw new InvalidOperationException();

            if (!delta.TryGetValue(nameof(DeltaAnnotated <T> .DeltaLink), out var deltaLink))
            {
                throw new InvalidOperationException();
            }

            if (!deltaLink.TryGetAttribute <JsonPropertyNameAttribute>(out var attribute))
            {
                throw new InvalidOperationException();
            }

            DeltaLinkName = attribute.Name;
        }
        static JsonNextLinkConverter()
        {
            var page = AccessorMembers.Create(typeof(NextLinkAnnotated <T>), AccessorMemberTypes.Properties, AccessorMemberScope.Public)
                       ?? throw new InvalidOperationException();

            if (!page.TryGetValue(nameof(NextLinkAnnotated <T> .NextLink), out var nextLink))
            {
                throw new InvalidOperationException();
            }

            if (!nextLink.TryGetAttribute <JsonPropertyNameAttribute>(out var attribute))
            {
                throw new InvalidOperationException();
            }

            NextLinkName = attribute.Name;
        }
Beispiel #16
0
        public IActionResult GetEmbedded(ApiVersion apiVersion, Guid id, string embeddedCollectionName, CancellationToken cancellationToken)
        {
            var members = AccessorMembers.Create(typeof(T), AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            foreach (var member in members)
            {
                if (!member.Type.ImplementsGeneric(typeof(IEnumerable <>)) || !member.Type.IsGenericType)
                {
                    continue; // not a collection
                }
                var arguments = member.Type.GetGenericArguments();
                var embeddedCollectionType = arguments[0];

                if (!typeof(IResource).IsAssignableFrom(embeddedCollectionType))
                {
                    continue; // not a resource collection
                }
                if (!_changeLog.TryGetResourceNameForType(embeddedCollectionType, out var name))
                {
                    name = embeddedCollectionType.Name;
                }

                if (!embeddedCollectionName.Equals(name.Pluralize(), StringComparison.OrdinalIgnoreCase))
                {
                    return(NotFound());
                }

                var controllerType = typeof(ResourceController <>).MakeGenericType(embeddedCollectionType);
                if (!(HttpContext.RequestServices.GetService(controllerType) is IResourceController controller))
                {
                    return(NotFound());
                }

                if (controller is Controller mvcController)
                {
                    mvcController.ControllerContext = new ControllerContext(ControllerContext);
                }

                // FIXME: implement filters and add parent ID in the filter

                return(controller.Get(apiVersion, cancellationToken));
            }

            // this is a generic 404, to avoid leaking mappings
            return(NotFound());
        }
Beispiel #17
0
        private void MaybeCacheObject(ActionExecutedContext context)
        {
            if (!(context.Result is OkObjectResult result))
            {
                return;
            }

            var body = result.Value;

            var cacheKey = context.HttpContext.Request.GetDisplayUrl();
            var json     = JsonSerializer.Serialize(body, _options);
            var etag     = _generator.GenerateFromBuffer(Encoding.UTF8.GetBytes(json));

            context.HttpContext.Response.Headers.Add(HeaderNames.ETag, new[] { etag });
            _cache.Save(cacheKey, etag);

            var members = AccessorMembers.Create(body, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            foreach (var member in members)
            {
                if (member.HasAttribute <CacheTimestampAttribute>())
                {
                    var accessor = ReadAccessor.Create(body);
                    if (accessor.TryGetValue(body, member.Name, out var lastModifiedDate))
                    {
                        switch (lastModifiedDate)
                        {
                        case DateTimeOffset timestamp:
                            context.HttpContext.Response.Headers.Add(HeaderNames.LastModified,
                                                                     timestamp.ToString("R"));
                            _cache.Save(cacheKey, timestamp);
                            break;

                        case DateTime timestamp:
                            context.HttpContext.Response.Headers.Add(HeaderNames.LastModified,
                                                                     timestamp.ToString("R"));
                            _cache.Save(cacheKey, timestamp);
                            break;
                        }
                    }
                }
            }
        }
        public async Task <Operation <IEnumerable <T> > > FetchAsync <T>(CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                var members = AccessorMembers.Create(typeof(T), AccessorMemberTypes.Properties, AccessorMemberScope.Public);
                var result  = await members.SelectAsync <T>(_dialect, _connectionString, cancellationToken : cancellationToken);

                return(Operation.FromResult(result));
            }
            catch (StorageException e)
            {
                return(Operation.FromResult(Enumerable.Empty <T>(), new List <Error>
                {
                    new Error(ErrorEvents.AggregateErrors, e.Message)
                }));
            }
        }
        public async Task <Operation <ObjectAppend> > CreateAsync(object @object, CancellationToken cancellationToken = default, params string[] fields)
        {
            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                var members = AccessorMembers.Create(@object, AccessorMemberTypes.Properties, AccessorMemberScope.Public);
                var hash    = members.ToHash(@object, fields, _provider, _transforms);
                await members.InsertAsync(_dialect, _connectionString, hash, cancellationToken);

                return(Operation.FromResult(ObjectAppend.Created));
            }
            catch (StorageException e)
            {
                return(Operation.FromResult(ObjectAppend.Error, new List <Error>
                {
                    new Error(ErrorEvents.AggregateErrors, e.Message)
                }));
            }
        }
Beispiel #20
0
        public PropertyAccessor(ITypeReadAccessor reads, ITypeWriteAccessor writes, Type type, string name)
        {
            Type = type;
            Name = name;

            _reads  = reads;
            _writes = writes;

            var members = AccessorMembers.Create(type);

            Info = members.PropertyInfo.SingleOrDefault(m => m.Name == name);

            var member = members.SingleOrDefault(p => p.Name == name);

            if (member == null)
            {
                return;
            }
            _member = member;
        }
Beispiel #21
0
        internal static Type GetPropertyTypeFromPath(Type type, string path, IContractResolver contractResolver)
        {
            var currentType    = type;
            var currentMembers = AccessorMembers.Create(type, AccessorMemberTypes.Fields | AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            foreach (var propertyName in path.Split(pathSplitter, StringSplitOptions.RemoveEmptyEntries))
            {
                var jsonContract = contractResolver.ResolveContract(currentType);
                if (jsonContract is JsonDictionaryContract jsonDictionaryContract)
                {
                    currentType = jsonDictionaryContract.DictionaryValueType;
                    continue;
                }

                if (currentMembers.TryGetValue(propertyName, out var member))
                {
                    currentType = member.Type;
                }
            }

            return(currentType);
        }
        private void DocumentSchemas(OperationFilterContext context)
        {
            // This will run multiple times, so we store previously discovered types
            foreach (var(typeName, schema) in context.SchemaRepository.Schemas)
            {
                if (!_registry.GetOrRegisterByName(typeName, out var type) || type == default)
                {
                    continue;
                }

                var members = AccessorMembers.Create(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

                foreach (var(propertyName, property) in schema.Properties)
                {
                    if (!members.TryGetValue(propertyName, out var member))
                    {
                        continue;
                    }
                    if (!member.TryGetAttribute(out DisplayAttribute attribute))
                    {
                        continue;
                    }

                    var description = attribute.GetDescription();
                    if (!string.IsNullOrWhiteSpace(description))
                    {
                        property.Description = _localizer.GetString(description);
                    }

                    var prompt = attribute.GetPrompt();
                    if (!string.IsNullOrWhiteSpace(prompt))
                    {
                        property.Example = new OpenApiString(_localizer.GetString(prompt));
                    }
                }
            }
        }
Beispiel #23
0
        private void ValidateTypeExistsInChangeLog(string resourceName, ApiVersion version, Type type, IReadOnlySet <Type> typesToSearch, bool addMissingResources = true)
        {
            if (!typesToSearch.Contains(type))
            {
                if (addMissingResources)
                {
                    AddMissingResource(version, type);
                }
                else
                {
                    // FIXME: localize
                    var message = string.Format("Resource '{0}' binds type '{1}', but this type was not found in the change log. Did you forget to add it?", resourceName, type.Name);
                    throw new ChangeLogException(message);
                }
            }

            var members = AccessorMembers.Create(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            foreach (var member in members)
            {
                if (typeof(IResource).IsAssignableFrom(member.Type))
                {
                    ValidateTypeExistsInChangeLog(resourceName, version, member.Type, typesToSearch, addMissingResources);
                }

                if (member.Type.ImplementsGeneric(typeof(IEnumerable <>)) && member.Type.IsGenericType)
                {
                    var arguments      = member.Type.GetGenericArguments();
                    var underlyingType = arguments[0];
                    if (typeof(IResource).IsAssignableFrom(underlyingType))
                    {
                        ValidateTypeExistsInChangeLog(resourceName, version, underlyingType, typesToSearch, addMissingResources);
                    }
                }
            }
        }
Beispiel #24
0
        public bool CanConvertFrom(Type type)
        {
            var members = AccessorMembers.Create(type, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            return(members.TryGetValue("Type", out _));
        }
Beispiel #25
0
        public override ValueTask <RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values)
        {
            const string routeKey = "route";

            if (!values.TryGetValue(routeKey, out var route) || !(route is string routeValue) ||
                string.IsNullOrWhiteSpace(routeValue))
            {
                return(new ValueTask <RouteValueDictionary>(values));
            }

            values.Remove(routeKey);

            var components = httpContext.RequestServices.GetServices <IDynamicFeature>();

            foreach (var component in components)
            {
                if (component.GetRouteTemplate == null)
                {
                    continue;
                }

                var prefix = component.GetRouteTemplate();
                if (prefix.StartsWith('/'))
                {
                    prefix = prefix.Substring(1);
                }

                if (!routeValue.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                var action = prefix == string.Empty? routeValue : routeValue.Replace($"{prefix}/", string.Empty);

                foreach (var controllerType in component.ControllerTypes)
                {
                    if (!IsValidForRequest(controllerType, httpContext))
                    {
                        continue;
                    }

                    var methods = AccessorMembers.Create(controllerType, AccessorMemberTypes.Methods,
                                                         AccessorMemberScope.Public);

                    foreach (var method in methods)
                    {
                        foreach (var attribute in method.Attributes)
                        {
                            if (attribute is NonActionAttribute)
                            {
                                continue;
                            }

                            if (!(attribute is DynamicHttpMethodAttribute httpMethod))
                            {
                                continue;
                            }

                            if (!httpMethod.HttpMethods.Contains(httpContext.Request.Method, StringComparer.OrdinalIgnoreCase))
                            {
                                continue;
                            }

                            var template = GetHttpTemplate(httpMethod, method);
                            if (template == string.Empty)
                            {
                                template = prefix;
                            }

                            if (!IsMatch(template, $"/{action}", httpContext, method, out var extraValues))
                            {
                                continue;
                            }

                            values["controller"] = ResolveControllerName(controllerType);
                            values["action"]     = ResolveActionName(method);

                            if (extraValues != null && extraValues.Count > 0)
                            {
                                foreach (var(k, v) in extraValues)
                                {
                                    values[k] = v;
                                }
                            }

                            return(new ValueTask <RouteValueDictionary>(values));
                        }
                    }
                }
            }

            return(NotFound(values));
        }
        public override async Task OnValidRequestAsync(Type underlyingType, StringValues clauses, ActionExecutingContext context, ActionExecutionDelegate next)
        {
            var members = AccessorMembers.Create(underlyingType, AccessorMemberTypes.Properties, AccessorMemberScope.Public);

            var inclusions = new List <string>();

            foreach (var value in clauses)
            {
                var fields = value.Split(new[] { ',' },
                                         StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
                if (fields.Length == 0)
                {
                    continue; // (FIXME: add a validation error?)
                }
                foreach (var field in fields)
                {
                    if (!members.TryGetValue(field, out var member) || inclusions.Contains(member.Name))
                    {
                        continue;
                    }

                    inclusions.Add(member.Name);
                }
            }

            if (inclusions.Count == 0)
            {
                await next.Invoke();

                return;
            }

            context.HttpContext.Items.TryAdd(Constants.ShapingOperationContextKey, inclusions);

            var executed = await next.Invoke();

            if (executed.HttpContext.Items.ContainsKey(Constants.ShapingOperationContextKey))
            {
                executed.HttpContext.Items.Remove(Constants.ShapingOperationContextKey);

                _logger.LogWarning(_localizer.GetString("Shaping operation has fallen back to object-level shaping. " +
                                                        "This means that shaping was not performed by the underlying data store, and is likely " +
                                                        "performing excessive work to return discarded values."));
            }

            if (executed.Result is ObjectResult result && !(result.Value is ProblemDetails))
            {
                var body = executed.GetResultBody(result, out var settable);

                if (settable)
                {
                    if (body.GetType().ImplementsGeneric(typeof(IEnumerable <>)))
                    {
                        underlyingType = typeof(IEnumerable <>).MakeGenericType(underlyingType);
                    }

                    var shapingType = typeof(ShapedData <>).MakeGenericType(underlyingType);
                    var shaped      = Activator.CreateInstance(shapingType, body, inclusions);
                    result.Value = shaped;
                }
            }
        }
Beispiel #27
0
        private static void TryMapType(Type type, IDictionary <Type, List <MemberInfo> > map)
        {
            if (type == null)
            {
                return;
            }

            if (type.IsArray)
            {
                TryMapType(type.GetElementType(), map);
                return;
            }

            if (Filtered(type))
            {
                return;
            }

            if (!map.TryGetValue(type, out var list))
            {
                map.Add(type, list = new List <MemberInfo>());
            }

            foreach (var member in AccessorMembers.Create(type, AccessorMemberScope.Public))
            {
                switch (member.MemberType)
                {
                case AccessorMemberType.Property:
                {
                    if (!map.ContainsKey(member.Type))
                    {
                        TryMapType(member.Type, map);
                    }
                    list.Add(member.MemberInfo);
                    break;
                }

                case AccessorMemberType.Field:
                {
                    if (!map.ContainsKey(member.Type))
                    {
                        TryMapType(member.Type, map);
                    }
                    list.Add(member.MemberInfo);
                    break;
                }

                case AccessorMemberType.Method:
                {
                    list.Add(member.MemberInfo);
                    if (member.MemberInfo is MethodInfo method)
                    {
                        foreach (var parameter in method.GetParameters())
                        {
                            if (!map.ContainsKey(parameter.ParameterType))
                            {
                                TryMapType(parameter.ParameterType, map);
                            }
                        }
                    }
                    break;
                }

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }
        }
        private static void ScanMembersForAttributes(Type callerType, IDictionary <string, List <string> > translations)
        {
            foreach (var member in AccessorMembers.Create(callerType, AccessorMemberTypes.Properties,
                                                          AccessorMemberScope.Public))
            {
                if (member.TryGetAttribute(out DisplayAttribute display))
                {
                    var scope = callerType.Name;

                    if (!translations.TryGetValue(scope, out var list))
                    {
                        translations.Add(scope, list = new List <string>());
                    }

                    var description = display.Description;
                    if (!string.IsNullOrWhiteSpace(description))
                    {
                        list.Add(description);
                    }

                    var prompt = display.Prompt;
                    if (!string.IsNullOrWhiteSpace(prompt))
                    {
                        list.Add(prompt);
                    }

                    var name = display.Name;
                    if (!string.IsNullOrWhiteSpace(name))
                    {
                        list.Add(name);
                    }

                    var groupName = display.GroupName;
                    if (!string.IsNullOrWhiteSpace(groupName))
                    {
                        list.Add(groupName);
                    }
                }

                if (member.TryGetAttribute(out OneOfAttribute oneOf))
                {
                    var scope = callerType.Name;

                    if (!translations.TryGetValue(scope, out var list))
                    {
                        translations.Add(scope, list = new List <string>());
                    }

                    if (!string.IsNullOrWhiteSpace(oneOf.ErrorMessage))
                    {
                        list.Add(oneOf.ErrorMessage);
                    }

                    foreach (var value in oneOf.OneOfStrings)
                    {
                        if (!string.IsNullOrWhiteSpace(value))
                        {
                            list.Add(value);
                        }
                    }
                }
            }
        }
 public IEnumerable <AccessorMembers> GetMigrationSubjects()
 {
     yield return(AccessorMembers.Create(
                      typeof(LogEntry), AccessorMemberTypes.Properties, AccessorMemberScope.Public));
 }
 public static string ToTable <T>(this IEnumerable <T> values)
 {
     return(ToTable(values,
                    AccessorMembers.Create(typeof(T), AccessorMemberTypes.Fields | AccessorMemberTypes.Properties,
                                           AccessorMemberScope.Public).Names.ToArray()));
 }