rauhryan
2/13/2012 - 11:49 PM

How Dovetail implemented asset extensions from bottles

How Dovetail implemented asset extensions from bottles

using DovetailCRM.Core.Extensibility.Assets;
using DovetailCRM.Core.Web.ViewModels;
using DovetailCRM.Web.Controllers.Sites;
using FubuCore;
using FubuMVC.Core.Assets;
using FubuMVC.Core.Registration.Nodes;

namespace DovetailCRM.Packages.HR.Demo.Agent
{
    public class ViewSiteAssetExtension : IAssetExtension
    {
        public bool Matches(BehaviorChain chain)
        {
            return !chain.FirstCall().Method.Name.Contains("New") && chain.FirstCall().OutputType().CanBeCastTo<EditSiteViewModel>();
        }

        public void Extend(IAssetRequirements requirements)
        {
            requirements.Require("viewsite.demo.extension.css");
        }
    }
}
using FubuMVC.Core.Assets;
using FubuMVC.Core.Registration.Nodes;

namespace DovetailCRM.Core.Extensibility.Assets
{
    public interface IAssetExtension
    {
        bool Matches(BehaviorChain chain);
        void Extend(IAssetRequirements requirements);
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using FubuMVC.Core;
using FubuMVC.Core.Assets;
using FubuMVC.Core.Behaviors;
using FubuMVC.Core.Registration;
using FubuMVC.Core.Registration.Nodes;
using FubuMVC.Core.Registration.ObjectGraph;

namespace DovetailCRM.Core.Extensibility.Assets
{
    public class AssetExtensionPolicy : IConfigurationAction 
    {
        public void Configure(BehaviorGraph graph)
        {
            graph.Behaviors
                .Where(b => b.HasOutputBehavior() && b.ActionOutputType() != (Type) null)
                .Each(c => c.Prepend(new AssetExtensionNode(c,typeof(AssetExtensionBehavior))));
        }
    }


    public class AssetExtensionNode : BehaviorNode
    {
        private readonly BehaviorChain _chain;
        private readonly Type _behaviorType;

        public AssetExtensionNode(BehaviorChain chain, Type behaviorType)
        {
            _chain = chain;
            _behaviorType = behaviorType;
        }

        protected override ObjectDef buildObjectDef()
        {
            var objectDef = new ObjectDef
                                {
                                    Type = _behaviorType
                                };
            objectDef.DependencyByValue(_chain);
            return objectDef;
        }

        public override BehaviorCategory Category
        {
            get { return BehaviorCategory.Wrapper;}
        }
    }

    public class AssetExtensionBehavior : BasicBehavior
    {
        private readonly IAssetRequirements _requirements;
        private readonly IEnumerable<IAssetExtension> _extensions;
        private readonly BehaviorChain _chain;


        public AssetExtensionBehavior(IAssetRequirements requirements, IEnumerable<IAssetExtension> extensions, BehaviorChain chain) : base(PartialBehavior.Executes)
        {
            _requirements = requirements;
            _extensions = extensions;
            _chain = chain;
        }

        protected override FubuMVC.Core.DoNext performInvoke()
        {
            _extensions.Each(x =>
                                 {
                                    if(x.Matches(_chain)) {x.Extend(_requirements);}
                                 });
            return DoNext.Continue;
        }
    }
}