Click here to Skip to main content
15,891,777 members
Articles / Web Development / HTML

Signum Framework Tutorials Part 1 – Southwind Entities

Rate me:
Please Sign up or sign in to vote.
4.50/5 (12 votes)
14 Nov 2012LGPL315 min read 41.4K   2K   52  
Tutorial focused in writing the entities using Signum Framework, a Win/Web LINQ-enabled framework for writing data-centric applications.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Linq.Expressions;
using System.Reflection.Emit;
using System.Collections;
using System.ComponentModel;
using System.Resources;
using System.Globalization;
using Signum.Utilities.Properties;
using System.Collections.Concurrent;

namespace Signum.Utilities.Reflection
{
    public static class ReflectionTools
    { 
        public static bool FieldEquals(FieldInfo f1, FieldInfo f2)
        {
            return MemeberEquals(f1, f2);
        }

        public static bool PropertyEquals(PropertyInfo p1, PropertyInfo p2)
        {
            return MemeberEquals(p1, p2);
        }

        public static bool MethodEqual(MethodInfo m1, MethodInfo m2)
        {
            return MemeberEquals(m1, m2);
        }

        public static bool MemeberEquals(MemberInfo m1, MemberInfo m2)
        {
            if (m1 == m2)
                return true;

            if (m1.DeclaringType != m2.DeclaringType)
                return false;

            // Methods on arrays do not have metadata tokens but their ReflectedType
            // always equals their DeclaringType
            if (m1.DeclaringType != null && m1.DeclaringType.IsArray)
                return false;

            if (m1.MetadataToken != m2.MetadataToken || m1.Module != m2.Module)
                return false;

            if (m1 is MethodInfo)
            {
                MethodInfo lhsMethod = m1 as MethodInfo;

                if (lhsMethod.IsGenericMethod)
                {
                    MethodInfo rhsMethod = m2 as MethodInfo;

                    Type[] lhsGenArgs = lhsMethod.GetGenericArguments();
                    Type[] rhsGenArgs = rhsMethod.GetGenericArguments();
                    for (int i = 0; i < rhsGenArgs.Length; i++)
                    {
                        if (lhsGenArgs[i] != rhsGenArgs[i])
                            return false;
                    }
                }
            }

            return true;
        }


        public static PropertyInfo GetPropertyInfo<R>(Expression<Func<R>> property)
        {
            return BasePropertyInfo(property);
        }

        public static PropertyInfo GetPropertyInfo<T, R>(Expression<Func<T, R>> property)
        {
            return BasePropertyInfo(property);
        }

        public static PropertyInfo BasePropertyInfo(LambdaExpression property)
        {
            if (property == null)
                throw new ArgumentNullException("property");

            Expression body = property.Body;
            if (body.NodeType == ExpressionType.Convert)
                body = ((UnaryExpression)body).Operand;

            MemberExpression ex = body as MemberExpression;
            if (ex == null)
                throw new ArgumentException("The lambda 'property' should be an expression accessing a property");

            PropertyInfo pi = ex.Member as PropertyInfo;
            if (pi == null)
                throw new ArgumentException("The lambda 'property' should be an expression accessing a property");

            return pi;
        }

        public static ConstructorInfo GetConstuctorInfo<R>(Expression<Func<R>> constuctor)
        {
            return BaseConstuctorInfo(constuctor);
        }

        public static ConstructorInfo BaseConstuctorInfo(LambdaExpression constuctor)
        {
            if (constuctor == null)
                throw new ArgumentNullException("constuctor");

            Expression body = constuctor.Body;
            if (body.NodeType == ExpressionType.Convert)
                body = ((UnaryExpression)body).Operand;

            NewExpression ex = body as NewExpression;
            if (ex == null)
                throw new ArgumentException("The lambda 'constuctor' should be an expression constructing an object");

            return ex.Constructor;
        }


        public static FieldInfo GetFieldInfo<R>(Expression<Func<R>> field)
        {
            return BaseFieldInfo(field);
        }

        public static FieldInfo GetFieldInfo<T,R>(Expression<Func<T, R>> field)
        {
            return BaseFieldInfo(field);
        }

        public static FieldInfo BaseFieldInfo(LambdaExpression field)
        {
            if (field == null)
                throw new ArgumentNullException("field");

            Expression body = field.Body;
            if (body.NodeType == ExpressionType.Convert)
                body = ((UnaryExpression)body).Operand;

            MemberExpression ex = body as MemberExpression;
            if (ex == null)
                throw new ArgumentException("The lambda 'field' should be an expression accessing a field");

            FieldInfo pi = ex.Member as FieldInfo;
            if (pi == null)
                throw new ArgumentException("The lambda 'field' should be an expression accessing a field");

            return pi;
        }


        public static MemberInfo GetMemberInfo<R>(Expression<Func<R>> member)
        {
            return BaseMemberInfo(member);
        }

        public static MemberInfo GetMemberInfo<T, R>(Expression<Func<T, R>> member)
        {
            return BaseMemberInfo(member);
        }

        public static MemberInfo BaseMemberInfo(LambdaExpression member)
        {
            if (member == null)
                throw new ArgumentNullException("member");

            Expression body = member.Body;
            if (body.NodeType == ExpressionType.Convert)
                body = ((UnaryExpression)body).Operand;

            MemberExpression ex = body as MemberExpression;
            if (ex == null)
                throw new ArgumentException("The lambda 'member' should be an expression accessing a member");

            return  ex.Member;
        }

    
        public static MethodInfo GetMethodInfo(Expression<Action> method)
        {
            return BaseMethodInfo(method);
        }

        public static MethodInfo GetMethodInfo<T>(Expression<Action<T>> method)
        {
            return BaseMethodInfo(method);
        }

        public static MethodInfo GetMethodInfo<R>(Expression<Func<R>> method)
        {
            return BaseMethodInfo(method);
        }

        public static MethodInfo GetMethodInfo<T, R>(Expression<Func<T, R>> method)
        {
            return BaseMethodInfo(method);
        }

        public static MethodInfo BaseMethodInfo(LambdaExpression method)
        {
            if (method == null)
                throw new ArgumentNullException("method");

            Expression body = method.Body;
            if (body.NodeType == ExpressionType.Convert)
                body = ((UnaryExpression)body).Operand;

            MethodCallExpression ex = body as MethodCallExpression;
            if (ex == null)
                throw new ArgumentException("The lambda 'method' should be an expression calling a method");

            return ex.Method;
        }

        public static Type GetReceiverType<T, R>(Expression<Func<T, R>> lambda)
        {
            Expression body = lambda.Body;
            if (body.NodeType == ExpressionType.Convert)
                body = ((UnaryExpression)body).Operand;

            return ((MemberExpression)body).Expression.Type;
        }

        public static Func<T, P> CreateGetter<T, P>(MemberInfo m)
        {
            if ((m as PropertyInfo).TryCS(a => !a.CanRead) ?? false)
                return null;

            ParameterExpression p = Expression.Parameter(typeof(T), "p");
            var exp = Expression.Lambda(typeof(Func<T,P>), Expression.MakeMemberAccess(p, m), p);
            return (Func<T, P>)exp.Compile();
        }

        public static Func<T, object> CreateGetter<T>(MemberInfo m)
        {
            if ((m as PropertyInfo).TryCS(a => !a.CanRead) ?? false)
                return null;

            ParameterExpression p = Expression.Parameter(typeof(T), "p");
            Type lambdaType = typeof(Func<,>).MakeGenericType(typeof(T), typeof(object));
            var exp = Expression.Lambda(lambdaType, Expression.Convert(Expression.MakeMemberAccess(p, m), typeof(object)), p);
            return (Func<T, object>)exp.Compile();
        }

        public static Func<object, object> CreateGetterUntyped(Type type, MemberInfo m)
        {
            if ((m as PropertyInfo).TryCS(a => !a.CanRead) ?? false)
                return null;

            ParameterExpression p = Expression.Parameter(typeof(object), "p");
            Type lambdaType = typeof(Func<,>).MakeGenericType(typeof(object), typeof(object));
            var exp = Expression.Lambda(lambdaType, Expression.Convert(Expression.MakeMemberAccess(Expression.Convert(p, type), m), typeof(object)), p);
            return (Func<object, object>)exp.Compile();
        }

        public static Action<T, P> CreateSetter<T, P>(MemberInfo m)
        {
            if ((m as PropertyInfo).TryCS(a => !a.CanWrite) ?? false)
                return null;

            ParameterExpression t = Expression.Parameter(typeof(T), "t");
            ParameterExpression  p = Expression.Parameter(typeof(P), "p");
            var exp = Expression.Lambda(typeof(Action<T, P>), 
                Expression.Assign(Expression.MakeMemberAccess(t, m), p), t,p);
            return (Action<T, P>)exp.Compile();
        }

        //Replace when C# 4.0 is available
        public static Action<T, object> CreateSetter<T>(MemberInfo m)
        {
            if ((m as PropertyInfo).TryCS(a => !a.CanWrite) ?? false)
                return null;

            ParameterExpression t = Expression.Parameter(typeof(T), "t");
            ParameterExpression p = Expression.Parameter(typeof(object), "p");
            var exp = Expression.Lambda(typeof(Action<T, object>),
                Expression.Assign(Expression.MakeMemberAccess(t, m), Expression.Convert(p, m.ReturningType())), t, p);
            return (Action<T, object>)exp.Compile();
        }

        static Module module = ((Expression<Func<int>>)(() => 2)).Compile().Method.Module;

        //Replace when C# 4.0 is available
        public static Action<object, object> CreateSetterUntyped(Type type, MemberInfo m)
        {
            if ((m as PropertyInfo).TryCS(a => !a.CanWrite) ?? false)
                return null;

            ParameterExpression t = Expression.Parameter(typeof(object), "t");
            ParameterExpression p = Expression.Parameter(typeof(object), "p");
            var exp = Expression.Lambda(typeof(Action<object, object>),
                Expression.Assign(Expression.MakeMemberAccess(Expression.Convert(t, type), m), Expression.Convert(p, m.ReturningType())), t, p);
            return (Action<object, object>)exp.Compile();
        }

        public static bool IsNumber(Type type)
        {
            switch (Type.GetTypeCode(type.UnNullify()))
            {
                case TypeCode.Single: 
                case TypeCode.Double: 
                case TypeCode.Decimal: 

                case TypeCode.Byte:

                case TypeCode.Int16:
                case TypeCode.Int32: 
                case TypeCode.Int64: 
                case TypeCode.UInt16: 
                case TypeCode.UInt32:
                case TypeCode.UInt64: return true;
            }

            return false;
        }

        public static bool IsPercentage(string formatString, CultureInfo culture)
        {
            return formatString.HasText() && formatString.StartsWith("p", StringComparison.InvariantCultureIgnoreCase); 
        }

        public static object ParsePercentage(string value, Type targetType, CultureInfo culture)
        {
            value = value.Trim(culture.NumberFormat.PercentSymbol.ToCharArray());

            if (string.IsNullOrEmpty(value))
                return null; 

            switch (Type.GetTypeCode(targetType.UnNullify()))
            {
                case TypeCode.Single: return Single.Parse(value, culture) / 100.0f;
                case TypeCode.Double: return Double.Parse(value, culture) / 100.0;
                case TypeCode.Decimal: return Decimal.Parse(value, culture) / 100M;

                case TypeCode.Byte: return (Byte)(Byte.Parse(value, culture) / 100);

                case TypeCode.Int16: return (Int16)(Int16.Parse(value, culture) / 100);
                case TypeCode.Int32: return (Int32)(Int32.Parse(value, culture) / 100);
                case TypeCode.Int64: return (Int64)(Int64.Parse(value, culture) / 100);
                case TypeCode.UInt16: return (UInt16)(UInt16.Parse(value, culture) / 100);
                case TypeCode.UInt32: return (UInt32)(UInt32.Parse(value, culture) / 100);
                case TypeCode.UInt64: return (UInt64)(UInt64.Parse(value, culture) / 100);
                default:
                    throw new InvalidOperationException("targetType is not a number");
            }
        }

        public static T Parse<T>(string value)
        {
            if (typeof(T) == typeof(string))
                return (T)(object)value;

            if (value == null || value == "")
                return (T)(object)null;

            Type utype = typeof(T).UnNullify();
            if (utype.IsEnum)
                return (T)Enum.Parse(utype, (string)value);
            else
                return (T)Convert.ChangeType(value, utype);
        }

        public static object Parse(string value, Type type)
        {
            if (type == typeof(string))
                return (object)value;

            if (value == null || value == "")
                return (object)null;

            Type utype = type.UnNullify(); 
            if (utype.IsEnum)
                return Enum.Parse(utype, (string)value);
            else
                return Convert.ChangeType(value, utype);
        }

        public static T Parse<T>(string value, CultureInfo culture)
        {
            if (typeof(T) == typeof(string))
                return (T)(object)value;

            if (value == null || value == "")
                return (T)(object)null;

            Type utype = typeof(T).UnNullify();
            if (utype.IsEnum)
                return (T)Enum.Parse(utype, (string)value);
            else
                return (T)Convert.ChangeType(value, utype, culture);
        }

        public static object Parse(string value, Type type, CultureInfo culture)
        {
            if (type == typeof(string))
                return (object)value;

            if (value == null || value == "")
                return (object)null;

            Type utype = type.UnNullify();
            if (utype.IsEnum)
                return Enum.Parse(utype, (string)value);
            else
                return Convert.ChangeType(value, utype, culture);
        }

        public static bool TryParse<T>(string value, out T result)
        {
            object objResult;
            if (TryParse(value, typeof(T), out objResult))
            {
                result = (T)objResult;
                return true;
            }
            else
            {
                result = default(T);
                return false;
            }
        }

        public static bool TryParse(string value, Type type, out object result)
        {
            if (type == typeof(string))
            {
                result = value;
                return true;
            }

            result = null;

            if (string.IsNullOrEmpty(value))
            {
                if (Nullable.GetUnderlyingType(type) == null && type.IsValueType)
                {
                    return false;
                }
                return true;
            }

            Type utype = type.UnNullify();
            if (utype.IsEnum)
            {
                Enum _result;
                if (EnumExtensions.TryParse(value, utype, true, out _result))
                {
                    result = _result;
                    return true; 
                }
                else return false; 
            }
            else if (utype == typeof(bool))
            {
                bool _result;
                if (bool.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(char))
            {
                char _result;
                if (char.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(SByte))
            {
                SByte _result;
                if (SByte.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(byte))
            {
                byte _result;
                if (byte.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(Int16))
            {
                Int16 _result;
                if (Int16.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(UInt16))
            {
                UInt16 _result;
                if (UInt16.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(Int32))
            {
                Int32 _result;
                if (Int32.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(UInt32))
            {
                UInt32 _result;
                if (UInt32.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(Int64))
            {
                Int64 _result;
                if (Int64.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(UInt64))
            {
                UInt64 _result;
                if (UInt64.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(float))
            {
                float _result;
                if (float.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(double))
            {
                double _result;
                if (double.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(decimal))
            {
                decimal _result;
                if (decimal.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(DateTime))
            {
                DateTime _result;
                if (DateTime.TryParse(value, out _result))
                {
                    result = _result;
                    return true;
                }
                else return false; 
            }
            else if (utype == typeof(object))
            {
                result = value;
                return true;
            }
            else
            {
                TypeConverter converter = TypeDescriptor.GetConverter(utype);
                if(converter.CanConvertFrom(typeof(string)))
                {
                    try
                    {
                        result = converter.ConvertFromString(value);
                        return true;
                    }
                    catch (Exception)
                    {
                        return false;
                    }
                }
                else return false;
            }
        }

        public static T ChangeType<T>(object value)
        {
            if (value == null)
                return (T)(object)null;

            if (value.GetType() == typeof(T))
                return (T)value;
            else
            {
                Type utype = typeof(T).UnNullify();

                if (utype.IsEnum)
                {
                    if (value is string)
                        return (T)Enum.Parse(utype, (string)value);
                    else
                        return (T)Enum.ToObject(utype, value);
                }

                else
                    return (T)Convert.ChangeType(value, utype);
            }
        }

        public static object ChangeType(object value, Type type)
        {
            if (value == null)
                return null;

            if (value.GetType() == type)
                return value;
            else
            {
                Type utype = type.UnNullify();

                if (utype.IsEnum)
                {
                    if (value is string)
                        return Enum.Parse(utype, (string)value);
                    else
                        return Enum.ToObject(utype, value);
                }
                else
                    return Convert.ChangeType(value, utype);
            }
        }
    }


    
}

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