Click here to Skip to main content
15,885,757 members
Articles / Web Development / HTML

Signum Framework Tutorials Part 2 – Southwind Logic

Rate me:
Please Sign up or sign in to vote.
4.45/5 (6 votes)
15 Nov 2012LGPL325 min read 31.3K   1K   22  
In this part, we will focus on writing business logic, LINQ queries and explain inheritance
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Signum.Utilities;
using System.Web;
using Signum.Entities;
using Signum.Entities.Basics;
using System.Reflection;
using Signum.Entities.Reflection;
using Signum.Entities.DynamicQuery;
using System.Web.Mvc;
using Signum.Engine;
using Signum.Web.Properties;
using Signum.Engine.DynamicQuery;

namespace Signum.Web
{
    public static class Constructor
    {
        public static ConstructorManager ConstructorManager;

        public static void Start(ConstructorManager constructorManager)
        {
            ConstructorManager = constructorManager;
        }

        public static ModifiableEntity Construct(Type type)
        {
            return ConstructorManager.Construct(type);
        }

        public static T Construct<T>() where T : ModifiableEntity
        {
            return (T)ConstructorManager.Construct(typeof(T));
        }

        public static ActionResult VisualConstruct(ControllerBase controller, Type type, string prefix, VisualConstructStyle preferredStyle)
        {
            return ConstructorManager.VisualConstruct(controller, type, prefix, preferredStyle);
        }

        public static void AddConstructor<T>(Func<T> constructor) where T:ModifiableEntity
        {
            ConstructorManager.Constructors.Add(typeof(T), constructor);
        }
    }

    public class ConstructContext
    {
        public ControllerBase Controller { get; set; }
        public Type Type { get; set; }
        public string Prefix { get; set; }
        public VisualConstructStyle PreferredViewStyle { get; set; }
    }
    
    public class ConstructorManager
    {
        public event Func<Type, ModifiableEntity> GeneralConstructor;
        public Dictionary<Type, Func<ModifiableEntity>> Constructors = new Dictionary<Type, Func<ModifiableEntity>>();

        public event Func<ConstructContext, ActionResult> VisualGeneralConstructor;
        public Dictionary<Type, Func<ConstructContext, ActionResult>> VisualConstructors = new Dictionary<Type, Func<ConstructContext, ActionResult>>();

        public virtual ModifiableEntity Construct(Type type)
        {
            Func<ModifiableEntity> c = Constructors.TryGetC(type);
            if (c != null)
            {
                ModifiableEntity result = c();
                if (result != null)
                    return result;
            }

            if (GeneralConstructor != null)
            {
                ModifiableEntity result = GeneralConstructor(type);
                if (result != null)
                    return result;
            }

            return DefaultContructor(type);
        }

        public static ModifiableEntity DefaultContructor(Type type)
        {
            return (ModifiableEntity)Activator.CreateInstance(type);
        }

        public virtual ActionResult VisualConstruct(ControllerBase controller, Type type, string prefix, VisualConstructStyle preferredStyle)
        {
            ConstructContext ctx = new ConstructContext { Controller = controller, Type = type, Prefix = prefix, PreferredViewStyle = preferredStyle };
            Func<ConstructContext, ActionResult> c = VisualConstructors.TryGetC(type);
            if (c != null)
            {
                ActionResult result = c(ctx);
                if (result != null)
                    return result;
            }

            if (VisualGeneralConstructor != null)
            {
                ActionResult result = VisualGeneralConstructor(ctx);
                if (result != null)
                    return result;
            }

            if (preferredStyle == VisualConstructStyle.Navigate)
                return JsonAction.Redirect(Navigator.ViewRoute(type, null));

            ModifiableEntity entity = Constructor.Construct(type);
            return EncapsulateView(controller, entity, prefix, preferredStyle); 
        }

        private ViewResultBase EncapsulateView(ControllerBase controller, ModifiableEntity entity, string prefix, VisualConstructStyle preferredStyle)
        {
            IdentifiableEntity ident = entity as IdentifiableEntity;

            if (ident == null)
                throw new InvalidOperationException("Visual Constructor doesn't work with EmbeddedEntities"); 

            AddFilterProperties(entity, controller);

            switch (preferredStyle)
            {
                case VisualConstructStyle.PopupView:
                    return Navigator.PopupView(controller, ident, prefix);
                case VisualConstructStyle.PartialView:
                    return Navigator.PartialView(controller, ident, prefix);
                case VisualConstructStyle.View:
                    return Navigator.View(controller, ident); 
                default:
                    throw new InvalidOperationException();
            }
        }

        public static void AddFilterProperties(ModifiableEntity obj, ControllerBase controller)
        {
            if (obj == null)
                throw new ArgumentNullException("result");

            HttpContextBase httpContext = controller.ControllerContext.HttpContext;

            if (!httpContext.Request.Params.AllKeys.Contains("webQueryName"))
                return;

            Type type = obj.GetType();

            object queryName = Navigator.ResolveQueryName(httpContext.Request.Params["webQueryName"]);

            QueryDescription queryDescription = DynamicQueryManager.Current.QueryDescription(queryName);

            var filters = FindOptionsModelBinder.ExtractFilterOptions(httpContext, queryDescription)
                .Where(fo => fo.Operation == FilterOperation.EqualTo);

            var pairs = from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                        join fo in filters on pi.Name equals fo.Token.Key
                        //where CanConvert(fo.Value, pi.PropertyType) && fo.Value != null
                        where fo.Value != null
                        select new { pi, fo };

            foreach (var p in pairs)
                p.pi.SetValue(obj, Common.Convert(p.fo.Value, p.pi.PropertyType), null);
        }
    }

    public enum VisualConstructStyle
    {
        PopupView, 
        PartialView,
        View,
        Navigate
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Software Developer (Senior) Signum Software
Spain Spain
I'm Computer Scientist, one of the founders of Signum Software, and the lead developer behind Signum Framework.

www.signumframework.com

I love programming in C#, Linq, Compilers, Algorithms, Functional Programming, Computer Graphics, Maths...

Comments and Discussions