Beispiel #1
0
        public override void init(RuntimeServices rs, InternalContextAdapter context, INode node)
        {
            base.init(rs, context, node);

            INode compNameNode = node.jjtGetChild(0);

            if (compNameNode == null)
            {
                String message = String.Format("You must specify the component name on the #component directive");
                throw new RailsException(message);
            }

            componentName = compNameNode.FirstToken.image;

            if (componentName == null)
            {
                String message = String.Format("Could not obtain component name from the #component directive");
                throw new RailsException(message);
            }

            component = viewComponentFactory.Create(componentName);
        }
Beispiel #2
0
        public override bool Render(IInternalContextAdapter context, TextWriter writer, INode node)
        {
            var railsContext     = EngineContextLocator.Instance.LocateCurrentContext();
            var registry         = railsContext.Services.GetService <IViewComponentFactory>().Registry;
            var viewDescProvider =
                railsContext.Services.GetService <IViewComponentDescriptorProvider>();
            var cacheProvider = railsContext.Services.CacheProvider;

            var compNameNode = node.GetChild(0);

            if (compNameNode == null)
            {
                var message = String.Format("You must specify the component name on the #{0} directive", Name);
                throw new ViewComponentException(message);
            }

            var componentName = compNameNode.FirstToken.Image;

            if (componentName == null)
            {
                var message = String.Format("Could not obtain component name from the #{0} directive", Name);
                throw new ViewComponentException(message);
            }

            if (componentName.StartsWith("$"))
            {
                var nodeContent = compNameNode.Literal.Trim('"', '\'');
                var inlineNode  = runtimeServices.Parse(new StringReader(nodeContent), context.CurrentTemplateName, false);

                inlineNode.Init(context, runtimeServices);
                componentName = (string)Evaluate(inlineNode, context);
            }

            var componentParams = CreateParameters(context, node);

            var viewComptype = registry.GetViewComponent(componentName);

            ViewComponentDescriptor descriptor = null;
            CacheKey key = null;

            if (viewComptype != null)
            {
                descriptor = viewDescProvider.Collect(viewComptype);
            }

            var isOutputtingToCache   = false;
            ViewComponentCacheBag bag = null;

            if (descriptor != null && descriptor.IsCacheable)
            {
                key = descriptor.CacheKeyGenerator.Create(componentName, componentParams, railsContext);

                if (key != null)
                {
                    var cachedContent = (ViewComponentCacheBag)cacheProvider.Get(key.ToString());

                    if (cachedContent != null)
                    {
                        // Restore entries

                        foreach (var pair in cachedContent.ContextEntries)
                        {
                            context[pair.Key] = pair.Value;
                        }

                        // Render from cache

                        writer.Write(cachedContent.Content);

                        return(true);
                    }

                    isOutputtingToCache = true;
                    bag = new ViewComponentCacheBag();
                }
            }

            var component = viewComponentFactory.Create(componentName);

            if (component == null)
            {
                throw new MonoRailException("ViewComponentFactory returned a null ViewComponent for " + componentName + ". " +
                                            "Please investigate the implementation: " + viewComponentFactory.GetType().FullName);
            }

            try
            {
                var directiveNode = (ASTDirective)node;
                var renderer      = (IViewRenderer)directiveNode.Directive;

                var contextAdapter = new NVelocityViewContextAdapter(componentName, node, viewEngine, renderer)
                {
                    Context = isOutputtingToCache ? new CacheAwareContext(context, bag) : context
                };

                INode bodyNode = null;

                if (node.ChildrenCount > 0)
                {
                    bodyNode = node.GetChild(node.ChildrenCount - 1);
                }

                var output = isOutputtingToCache ? bag.CacheWriter : writer;

                contextAdapter.BodyNode        = bodyNode;
                contextAdapter.ComponentParams = componentParams;
                contextAdapter.TextWriter      = output;

                component.Init(railsContext, contextAdapter);

                ProcessSubSections(component, contextAdapter);

                const string ViewComponentContextKey = "viewcomponent";
                var          previousComp            = context[ViewComponentContextKey];

                try
                {
                    context[ViewComponentContextKey] = component;

                    component.Render();

                    if (contextAdapter.ViewToRender != null)
                    {
                        RenderComponentView(context, contextAdapter.ViewToRender, output, contextAdapter);
                    }

                    if (isOutputtingToCache)
                    {
                        // Save output

                        cacheProvider.Store(key.ToString(), bag);

                        // Output to correct writer

                        writer.Write(bag.Content);
                    }
                }
                finally
                {
                    if (previousComp != null)
                    {
                        context[ViewComponentContextKey] = previousComp;
                    }
                    else
                    {
                        context.Remove(ViewComponentContextKey);
                    }
                }
            }
            finally
            {
                viewComponentFactory.Release(component);
            }

            return(true);
        }