private IProjectionMetadata GetMetadataForModel(PageDescriptor descriptor, ProcArgs args, IDomainOptions options)
        {
            Type pageType = this.GetModelTypeFromPage(descriptor.PageType);
            Type argsType = args.ModelType ?? typeof(object);

            ISchema pageSchema = options.Schemas.GetSchema(pageType);
            ISchema argsSchema = options.Schemas.GetSchema(argsType);

            IProjectionMetadata pageMetadata = pageSchema.Require <IProjectionMetadata>();
            IProjectionMetadata argsMetadata = argsSchema.Require <IProjectionMetadata>();

            if (argsMetadata.Item != null && pageMetadata.Type.IsAssignableFrom(argsMetadata.Item.Type))
            {
                return(argsMetadata.Item);
            }
            else if (pageMetadata.Type.IsAssignableFrom(argsMetadata.Type))
            {
                return(argsMetadata);
            }
            else if (argsMetadata.Type.IsAssignableFrom(pageMetadata.Type))
            {
                return(pageMetadata);
            }
            else
            {
                throw new InvalidOperationException($"No conversion found between page type '{pageMetadata.Type.FullName}' and requested type '{argsMetadata.Type.FullName}'.");
            }
        }
Beispiel #2
0
        private IProcResult ExecuteAndGetResult(string procName, object model, ProcArgs args)
        {
            IProcLocator locator = this.Context?.Locator ?? new ProcLocator();
            IProcEngine  engine  = this.Context?.Engine ?? new ProcEngine(null);

            PageDescriptor descriptor = locator.FindPage(procName, this.GetType());
            ProcFactory    factory    = engine.Proc(descriptor, args);

            return(factory(model));
        }
Beispiel #3
0
        public ProcCacheKey(PageDescriptor descriptor, ProcArgs args)
        {
            if (descriptor == null)
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            this.PageType   = descriptor.PageType;
            this.ModelType  = args.ModelType;
            this.ResultType = args.ResultType;
        }
        private IProjectionMetadata GetMetadataForResult(PageDescriptor descriptor, ProcArgs args, IDomainOptions options)
        {
            Type itemType = this.GetResultTypeFromPage(descriptor.PageType);
            Type pageType = typeof(IList <>).MakeGenericType(itemType);
            Type argsType = args.ResultType ?? typeof(IReadOnlyList <object>);

            ISchema pageSchema = options.Schemas.GetSchema(pageType);
            ISchema argsSchema = options.Schemas.GetSchema(argsType);

            IProjectionMetadata pageMetadata = pageSchema.Require <IProjectionMetadata>();
            IProjectionMetadata argsMetadata = argsSchema.Require <IProjectionMetadata>();

            if (pageMetadata.Item != null && argsMetadata.Item != null && pageMetadata.Item.Type.IsAssignableFrom(argsMetadata.Item.Type))
            {
                return(argsMetadata.Item);
            }
            else if (pageMetadata.Item != null && argsMetadata.Item != null && argsMetadata.Item.Type.IsAssignableFrom(pageMetadata.Item.Type))
            {
                return(pageMetadata.Item);
            }
            else if (pageMetadata.Item != null && pageMetadata.Item.Type.IsAssignableFrom(argsMetadata.Type))
            {
                return(argsMetadata);
            }
            else if (argsMetadata.Item != null && argsMetadata.Item.Type.IsAssignableFrom(pageMetadata.Type))
            {
                return(pageMetadata);
            }
            else if (argsMetadata.Type.IsAssignableFrom(pageMetadata.Type))
            {
                return(pageMetadata);
            }
            else if (pageMetadata.Type.IsAssignableFrom(argsMetadata.Type))
            {
                return(argsMetadata);
            }
            else
            {
                throw new InvalidOperationException($"No conversion found between page type '{pageMetadata.Type.GetSanitizedFullName()}' and requested type '{argsMetadata.Type.GetSanitizedFullName()}'.");
            }
        }
        public ProcFactory Proc(PageDescriptor descriptor, ProcArgs args)
        {
            if (descriptor == null)
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            if (descriptor.DomainType == null)
            {
                throw ProcExecutionException.DomainNotFound(descriptor.PageType);
            }

            ProcCacheKey key = new ProcCacheKey(descriptor, args);

            return(ProcCache.Procs.GetOrAdd(key, _ => this.CreateProcFactory(descriptor, args)));
        }
Beispiel #6
0
        public ProcFactory Proc(PageDescriptor descriptor, ProcArgs args)
        {
            if (descriptor == null)
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            if (args == null)
            {
                throw new ArgumentNullException(nameof(args));
            }

            if (descriptor.DomainType == null)
            {
                throw new ProcExecutionException($"No domain found for page type '{descriptor.PageType.GetSanitizedFullName()}'. Make sure to implement IDomain in a parent namespace.");
            }

            ProcCacheKey key = new ProcCacheKey(descriptor, args);

            return(ProcCache.Procs.GetOrAdd(key, _ => this.CreateProcFactory(descriptor, args)));
        }
        private ProcFactory CreateProcFactory(PageDescriptor descriptor, ProcArgs args)
        {
            IDomainOptions options = this.Options(descriptor.DomainType);

            PageDescriptor[]  template  = this.GetTemplateHierarchy(descriptor).Reverse().ToArray();
            PageConstructor[] factories = template.Select(t => this.CreatePageConstructor(t.PageType)).Concat(new PageConstructor[1]).ToArray();

            IProjectionMetadata resultMetadata = this.GetMetadataForResult(descriptor, args, options);
            IProjectionMetadata modelMetadata  = this.GetMetadataForModel(descriptor, args, options);

            ISchema resultSchema = resultMetadata.Identity.Schema;
            ISchema modelSchema  = modelMetadata.Identity.Schema;

            IProcLocator locator = descriptor.Locator;

            Type originType = descriptor.OriginType;

            IProcResult procFactory(object model)
            {
                ProcContext context = this.CreateContext(descriptor);

                ProjectionIdentity modelIdentity  = new ProjectionIdentity(new Model(modelSchema, model));
                ProjectionIdentity resultIdentity = new ProjectionIdentity(resultSchema);

                IProjection modelProjection  = new Projection(modelIdentity, context, modelMetadata);
                IProjection resultProjection = new Projection(resultIdentity, context, resultMetadata);

                PageExecutionContext[] execution = template.Select(t => new PageExecutionContext()
                {
                    Page = t
                }).ToArray();

                execution[0].Buffer = new ProcBuffer();

                for (int i = 0; i < execution.Length; i++)
                {
                    PageConstructor nextFactory = factories[i + 1];

                    if (nextFactory != null)
                    {
                        PageExecutionContext nextContext = execution[i + 1];

                        execution[i].Body = () =>
                        {
                            ISqlPage bodyPage = nextFactory(modelProjection, resultProjection);

                            context.Stack.Push(nextContext);

                            bodyPage.Execute();

                            context.Stack.Pop();
                        };
                    }
                }

                ISqlPage page = factories[0](modelProjection, resultProjection);

                context.Stack.Push(execution[0]);

                page.Execute();

                return(new ProcResult()
                {
                    Buffer = context.Execution.Buffer,
                    Domain = options,
                });
            }

            return(procFactory);
        }