示例#1
0
        public DocumentDesigner <TEntity> With <TMember, TReturn>(string name, Expression <Func <TEntity, TMember> > projector, Func <TMember, TReturn> converter, params Option[] options)
        {
            if (typeof(TReturn) == typeof(string))
            {
                options = options.Concat(new MaxLength(850)).ToArray();
            }

            var column = design.Table[name];

            if (DocumentTable.IdColumn.Equals(column))
            {
                throw new ArgumentException("You can not make a projection for IdColumn. Use Document.Key() method instead.");
            }

            if (column == null)
            {
                var lengthOption = options
                                   .OfType <MaxLength>()
                                   .FirstOrDefault();

                column = design.Table.Add(new Column <TReturn>(name, lengthOption?.Length));
            }

            Func <object, object> compiledProjector;

            if (!options.OfType <DisableNullCheckInjection>().Any())
            {
                var nullCheckInjector    = new NullCheckInjector();
                var nullCheckedProjector = (Expression <Func <TEntity, object> >)nullCheckInjector.Visit(projector);

                if (!nullCheckInjector.CanBeTrustedToNeverReturnNull && !column.IsPrimaryKey)
                {
                    column.Nullable = true;
                }

                compiledProjector = Compile(name, nullCheckedProjector);
            }
            else
            {
                compiledProjector = Compile(name, projector);
            }

            var newProjection = Projection.From <TReturn>(document =>
            {
                var value = compiledProjector(document);

                if (value == null)
                {
                    return(null);
                }

                return(converter((TMember)value));
            });

            if (!newProjection.ReturnType.IsCastableTo(column.Type))
            {
                throw new InvalidOperationException(
                          $"Can not override projection for {name} of type {column.Type} " +
                          $"with a projection that returns {newProjection.ReturnType} (on {typeof (TEntity)}).");
            }

            Projection existingProjection;

            if (!design.Projections.TryGetValue(name, out existingProjection))
            {
                if (design.Parent != null && !column.IsPrimaryKey)
                {
                    column.Nullable = true;
                }

                design.Projections.Add(column, newProjection);
            }
            else
            {
                design.Projections[name] = newProjection;
            }

            return(this);
        }