Click here to Skip to main content
15,895,799 members
Articles / Web Development / ASP.NET

Signum Framework Principles

Rate me:
Please Sign up or sign in to vote.
4.74/5 (27 votes)
25 Jul 2011CPOL18 min read 99.5K   1.1K   86  
Explains the philosophy behind Signum Framework, an ORM with a full LINQ Provider that encourages an entities-first approach.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.ComponentModel;
using System.Text.RegularExpressions;
using Signum.Utilities;
using Signum.Utilities.ExpressionTrees;
using System.Windows.Data;
using Signum.Utilities.DataStructures;
using System.Reflection;
using System.Windows.Media;
using Signum.Entities.Reflection;
using Signum.Windows.Properties;
using System.Collections;

namespace Signum.Windows
{
    public static class Common
    {
        public static double GetLabelWidth(DependencyObject obj)
        {
            return (double)obj.GetValue(LabelWidthProperty);
        }
        public static void SetLabelWidth(DependencyObject obj, double value)
        {
            obj.SetValue(LabelWidthProperty, value);
        }
        public static readonly DependencyProperty LabelWidthProperty =
            DependencyProperty.RegisterAttached("LabelWidth", typeof(double), typeof(Common), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.Inherits));


        public static bool GetLabelVisible(DependencyObject obj)
        {
            return (bool)obj.GetValue(LabelVisibleProperty);
        }

        public static void SetLabelVisible(DependencyObject obj, bool value)
        {
            obj.SetValue(LabelVisibleProperty, value);
        }
        public static readonly DependencyProperty LabelVisibleProperty =
            DependencyProperty.RegisterAttached("LabelVisible", typeof(bool), typeof(Common), new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));



        public static bool GetIsReadOnly(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsReadOnlyProperty); 
        }

        public static void SetIsReadOnly(DependencyObject obj, bool value)
        {
            obj.SetValue(IsReadOnlyProperty, value);
        }

        public static readonly DependencyProperty IsReadOnlyProperty =
            DependencyProperty.RegisterAttached("IsReadOnly", typeof(bool), typeof(Common), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits));


        public static TypeContext GetTypeContext(DependencyObject obj)
        {
            return (TypeContext)obj.GetValue(TypeContextProperty);
        }

        public static void SetTypeContext(DependencyObject obj, TypeContext value)
        {
            obj.SetValue(TypeContextProperty, value);
        }

        // Using a DependencyProperty as the backing store for TypeContext.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TypeContextProperty =
            DependencyProperty.RegisterAttached("TypeContext", typeof(TypeContext), typeof(Common), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits));


        public static string GetRoute(DependencyObject obj)
        {
            return (string)obj.GetValue(RouteProperty);
        }

        public static void SetRoute(DependencyObject obj, string value)
        {
            obj.SetValue(RouteProperty, value);
        }
        public static readonly DependencyProperty RouteProperty =
            DependencyProperty.RegisterAttached("Route", typeof(string), typeof(Common), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(RoutePropertyChanged)));

     
        static readonly Regex validIdentifier = new Regex(@"^[_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nl}][_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nl}\p{Nd}]*$");
        public static void RoutePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement fe = (FrameworkElement)d;

            DependencyProperty labelText =
                 fe is ValueLine ? ValueLine.LabelTextProperty :
                 fe is EntityBase ? EntityBase.LabelTextProperty :
                 null;

            if (DesignerProperties.GetIsInDesignMode(fe))
            {
                if (labelText != null && fe.NotSet(labelText))
                {
                    fe.SetValue(labelText, e.NewValue);
                }

                return;

            }

            string route = (string)e.NewValue;

            TypeContext context = GetTypeContext(fe.Parent);

            if (context == null)
                throw new ApplicationException(Properties.Resources.RoutePropertyCanNotBeAppliedWithNullTypeContext);

            string nRoute = route.Replace("/", "./.");
            string[] steps = nRoute.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var step in steps)
            {
                if (step == "/")
                {
                    if(!typeof(IList).IsAssignableFrom(context.Type))
                        throw new InvalidOperationException(Resources.Type0IsNotAColection.Formato(context.Type.TypeName()));

                    context = new TypeSubContext(context.Type.GetProperty("Item"), context); 
                }
                else if (validIdentifier.IsMatch(step))
                {
                    PropertyInfo pi = context.Type.GetProperty(step).ThrowIfNullC(Resources.Property0DoNotExistOnType1.Formato(step, context.Type.TypeName()));
                    context = new TypeSubContext(pi, context); 
                }
            }

            SetTypeContext(fe, context); 

            DependencyProperty typeProperty =
                fe is ValueLine ? ValueLine.ValueTypeProperty :
                fe is EntityLine ? EntityLine.EntityTypeProperty :
                fe is EntityList ? EntityList.EntitiesTypeProperty :
                fe is EntityCombo ? EntityCombo.EntityTypeProperty :
                fe is FileLine ? FileLine.EntityTypeProperty :
                null;

            if (typeProperty != null && fe.NotSet(typeProperty))
            {
                fe.SetValue(typeProperty, context.Type);
                if (fe is EntityList)
                    fe.SetValue(EntityList.EntityTypeProperty, Reflector.CollectionType(context.Type));
            }



            if (labelText!= null && fe.NotSet(labelText))
            {
                fe.SetValue(labelText, steps.LastOrDefault());
            }


            DependencyProperty valueProp = 
                fe is ValueLine? ValueLine.ValueProperty:
                fe is EntityLine? EntityLine.EntityProperty: 
                fe is EntityList? EntityList.EntitiesProperty:
                fe is EntityCombo? EntityCombo.EntityProperty:
                fe is FileLine ? FileLine.EntityProperty :
                FrameworkElement.DataContextProperty;

            bool isReadOnly = (context as TypeSubContext).TryCS(tsc => tsc.IsReadOnly) ?? true;

            if (!BindingOperations.IsDataBound(fe, valueProp))
            {
                Binding b = new Binding(route);
                b.Mode =  isReadOnly? BindingMode.OneWay : BindingMode.TwoWay;
                b.NotifyOnValidationError = true;
                b.ValidatesOnExceptions = true;
                b.ValidatesOnDataErrors = true;
                fe.SetBinding(valueProp, b);
            }

            if (isReadOnly && (fe is ValueLine || fe is EntityLine || fe is EntityCombo || fe is FileLine))
            {
                Common.SetIsReadOnly(fe, true);
            }


            if (fe is EntityBase)
            {
                var contextList = context.FollowC(a => (a as TypeSubContext).TryCC(t => t.Parent)).ToList();

                if (contextList.Count > 1)
                {
                    var list = contextList.OfType<TypeSubContext>().Select(a => a.PropertyInfo).Reverse().ToList();
 
                    if(fe is EntityList)
                        list.Add( list.Last().PropertyType.GetProperty("Item"));

                    ((EntityBase)fe).Implementations = Server.ServerProxy.FindImplementations(contextList.Last().Type, list.Cast<MemberInfo>().ToArray());
                }
            }
        }



        public static Window GetCurrentWindow(DependencyObject obj)
        {
            return (Window)obj.GetValue(CurrentWindowProperty);
        }

        public static void SetCurrentWindow(DependencyObject obj, Window value)
        {
            obj.SetValue(CurrentWindowProperty, value);
        }

        // Using a DependencyProperty as the backing store for CurrentWindow.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CurrentWindowProperty =
            DependencyProperty.RegisterAttached("CurrentWindow", typeof(Window), typeof(Common), new FrameworkPropertyMetadata(null,  FrameworkPropertyMetadataOptions.Inherits));



        public static Window FindCurrentWindow(this FrameworkElement fe)
        {
            return fe.FollowC(a => (FrameworkElement)(a.Parent ?? a.TemplatedParent))
                      .Select(a => GetCurrentWindow(a) ?? a as Window).NotNull().First(Properties.Resources.ParentWindowNotFound);
        }


        public static bool NotSet(this DependencyObject depObj, DependencyProperty prop)
        {
            return DependencyPropertyHelper.GetValueSource(depObj, prop).BaseValueSource != BaseValueSource.Local;
        }


        public static IEnumerable<DependencyObject> Parents(this DependencyObject child)
        {
            return child.FollowC(VisualTreeHelper.GetParent); 
        }


        public static Visibility ToVisibility(this bool val)
        {
            return val ? Visibility.Visible : Visibility.Collapsed;
        }

        public static bool FromVisibility(this Visibility val)
        {
            return val == Visibility.Visible;
        }

        public static DependencyObject FindChildrenBreadthFirst(DependencyObject parent, Predicate<DependencyObject> predicate)
        {
            //http://en.wikipedia.org/wiki/Breadth-first_search
            Queue<DependencyObject> st = new Queue<DependencyObject>();
            st.Enqueue(parent);

            while (st.Count > 0)
            {
                DependencyObject dp = st.Dequeue();

                if (predicate(dp))
                    return dp;

                int count = VisualTreeHelper.GetChildrenCount(dp);
                for (int i = 0; i < count; i++)
                {
                    st.Enqueue(VisualTreeHelper.GetChild(dp, i));
                }
            }
            return null;
        }
      
    }
}

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 Code Project Open License (CPOL)


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