Esempio n. 1
0
        void Initialize()
        {
            if (_memberHandlers is null)
            {
                InitializeCore();
            }

            void InitializeCore()
            {
                var pgType = (PostgresCompositeType)PostgresType;

                _memberHandlers     = CreateMemberHandlers(pgType, _typeMapper, _nameTranslator);
                _constructorHandler = CreateConstructorHandler(pgType, _typeMapper, _nameTranslator);
                _constructor        = _constructorHandler is null
                    ? Expression
                                      .Lambda <Func <T> >(Expression.New(typeof(T)))
                                      .Compile()
                    : null;
            }
        }
Esempio n. 2
0
        static CompositeMemberHandler <T>[] CreateMemberHandlers(PostgresCompositeType pgType, ConnectorTypeMapper typeMapper, INpgsqlNameTranslator nameTranslator)
        {
            var pgFields = pgType.Fields;

            var clrType               = typeof(T);
            var clrMemberHandlers     = new CompositeMemberHandler <T> [pgFields.Count];
            var clrMemberHandlerCount = 0;
            var clrMemberHandlerType  = IsValueType <T> .Value
                ? typeof(CompositeStructMemberHandler <,>)
                : typeof(CompositeClassMemberHandler <,>);

            foreach (var clrProperty in clrType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                CreateMemberHandler(clrProperty, clrProperty.PropertyType);
            }

            foreach (var clrField in clrType.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                CreateMemberHandler(clrField, clrField.FieldType);
            }

            if (clrMemberHandlerCount != pgFields.Count)
            {
                var notMappedFields = string.Join(", ", clrMemberHandlers
                                                  .Select((member, memberIndex) => member == null ? $"'{pgFields[memberIndex].Name}'" : null)
                                                  .Where(member => member != null));
                throw new InvalidOperationException($"PostgreSQL composite type {pgType.DisplayName} contains fields {notMappedFields} which could not match any on CLR type {clrType.Name}");
            }

            return(clrMemberHandlers);

            void CreateMemberHandler(MemberInfo clrMember, Type clrMemberType)
            {
                var attr = clrMember.GetCustomAttribute <PgNameAttribute>();
                var name = attr?.PgName ?? nameTranslator.TranslateMemberName(clrMember.Name);

                for (var pgFieldIndex = pgFields.Count - 1; pgFieldIndex >= 0; --pgFieldIndex)
                {
                    var pgField = pgFields[pgFieldIndex];
                    if (pgField.Name != name)
                    {
                        continue;
                    }

                    if (clrMemberHandlers[pgFieldIndex] != null)
                    {
                        throw new AmbiguousMatchException($"Multiple class members are mapped to the '{pgField.Name}' field.");
                    }

                    if (!typeMapper.TryGetByOID(pgField.Type.OID, out var handler))
                    {
                        throw new NpgsqlException($"PostgreSQL composite type {pgType.DisplayName} has field {pgField.Type.DisplayName} with an unknown type (OID = {pgField.Type.OID}).");
                    }

                    clrMemberHandlerCount++;
                    clrMemberHandlers[pgFieldIndex] = (CompositeMemberHandler <T>)Activator.CreateInstance(
                        clrMemberHandlerType.MakeGenericType(clrType, clrMemberType),
                        BindingFlags.Instance | BindingFlags.Public,
                        binder: null,
                        args: new object[] { clrMember, pgField.Type, handler },
                        culture: null) !;

                    break;
                }
            }
        }