Click here to Skip to main content
15,881,248 members
Articles / Desktop Programming / WPF

Building WPF Applications with Self-Tracking Entity Generator and Visual Studio 2012 - Project Setup

Rate me:
Please Sign up or sign in to vote.
5.00/5 (14 votes)
17 Mar 2013CPOL8 min read 68.4K   3.5K   44  
This article describes the project setup of building a WPF sample application with Self-Tracking Entity Generator and Visual Studio 2012.
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Resources;
using System.Runtime.Serialization;
using System.Text;
using System.Xml.Linq;

#if (SILVERLIGHT || WPF)
namespace SchoolSample.EntityModel
{
    /// <summary>
    /// Class EnumCollection (of T) creates an object which contains
    /// a collection of every possible enum value of T where property Value
    /// stores the actual enum value and DisplayName keeps the display name.
    /// </summary>
    /// <typeparam name="T">enum type</typeparam>
    public class EnumCollection<T> : ICollection where T : struct
    {
        #region "EnumItem class"
    
        public class EnumItem : INotifyPropertyChanged
        {
            public string DisplayName
            {
                get { return _displayName; }
                set
                {
                    _displayName = value;
                    OnPropertyChanged("DisplayName");
                }
            }
    
            private string _displayName;
    
            public string ResourceEntryKey { get; set; }
    
            public T? Value
            {
                get { return _value; }
                set
                {
                    _value = value;
                    OnPropertyChanged("Value");
                }
            }
    
            private T? _value;
    
            private void OnPropertyChanged(String propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
        }
    
        #endregion
    
        #region "Private Data Member"
    
        private readonly Collection<EnumItem> enumItems;
        private readonly ResourceManager resourceManager;
    
        #endregion "Private Data Member"
    
        #region "Constructor"
    
        /// <summary>
        /// Static constructor to make sure that T is of Enum type
        /// </summary>
        static EnumCollection()
        {
            if (!typeof (T).IsEnum)
                throw new ArgumentException("T must be an enumerated type");
        }
    
        /// <summary>
        /// Constructor to initialize EnumCollection
        /// </summary>
        /// <param name="firstAsNull">True to add the first row as null</param>
        /// <param name="resourceManager">ResourceManager where DisplayName gets its value</param>
        public EnumCollection(bool firstAsNull = false, ResourceManager resourceManager = null)
        {
            enumItems = new Collection<EnumItem>();
            this.resourceManager = resourceManager;
    
            if (firstAsNull)
                enumItems.Add(new EnumItem
                                  {
                                      DisplayName = string.Empty,
                                      ResourceEntryKey = string.Empty,
                                      Value = null
                                  });
    
            var type = typeof (T);
            foreach (var enumValue in (from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
                                       where field.IsLiteral
                                       select (T) field.GetValue(null)))
            {
                if (resourceManager != null)
                {
                    var resourceEntryKey = string.Format("{0}_{1}", typeof (T).Name, enumValue);
                    var displayName = resourceManager.GetString(resourceEntryKey);
                    if (displayName != null)
                    {
                        enumItems.Add(new EnumItem
                                          {
                                              DisplayName = displayName,
                                              ResourceEntryKey = resourceEntryKey,
                                              Value = enumValue
                                          });
                    }
                    else
                    {
                        enumItems.Add(new EnumItem
                                          {
                                              DisplayName = string.Format("{0}_{1}", typeof (T).Name, enumValue),
                                              ResourceEntryKey = string.Empty,
                                              Value = enumValue
                                          });
                    }
                }
                else
                {
                    enumItems.Add(new EnumItem
                                      {
                                          DisplayName = string.Format("{0}", enumValue),
                                          ResourceEntryKey = string.Empty,
                                          Value = enumValue
                                      });
                }
            }
        }
    
        #endregion
    
        #region "Public Method & Property"
    
        /// <summary>
        /// Refreshes the DisplayName property for every item
        /// where the ResourceEntryKey property is not empty
        /// </summary>
        public void Refresh()
        {
            if (resourceManager == null) return;
            foreach (var item in enumItems.Where(n => !string.IsNullOrEmpty(n.ResourceEntryKey)))
            {
                var displayName = resourceManager.GetString(item.ResourceEntryKey);
                if (displayName != null) item.DisplayName = displayName;
            }
        }
    
        public Collection<EnumItem> Items
        {
            get { return enumItems; }
        }
    
        #endregion
    
        #region "ICollectionView implementation"
    
        public void CopyTo(Array array, int index)
        {
            ((ICollection) enumItems).CopyTo(array, index);
        }
    
        public int Count
        {
            get { return enumItems.Count; }
        }
    
        public bool IsSynchronized
        {
            get { return ((ICollection) enumItems).IsSynchronized; }
        }
    
        public object SyncRoot
        {
            get { return ((ICollection) enumItems).SyncRoot; }
        }
    
        public IEnumerator GetEnumerator()
        {
            return ((ICollection) enumItems).GetEnumerator();
        }
    
        #endregion
    }
    
    public class ValidationResultChangedEventArgs : EventArgs
    {
        public ValidationResultChangedEventArgs(string propertyName, IList<ValidationResult> removedItems, IList<ValidationResult> addedItems)
        {
            PropertyName = propertyName;
            RemovedItems = removedItems ?? new List<ValidationResult>();
            AddedItems = addedItems ?? new List<ValidationResult>();
        }
    
        public string PropertyName { get; private set; }
        public IList<ValidationResult> AddedItems { get; private set; }
        public IList<ValidationResult> RemovedItems { get; private set; }
    }
    
    // An interface that provides an event that fires when validation results changed
    public interface INotifyValidationResultChanged
    {
        event EventHandler<ValidationResultChangedEventArgs> ValidationResultChanged;
    }
    
    // An interface that defines the only method GetNextLevelNodes()
    // which computes the level of a node inside the object graph
    public interface INodeLevel
    {
        List<INodeLevel> GetNextLevelNodes(Dictionary<INodeLevel, int> nodeLevelDictionary);
    }
    
    // An interface that provides methods and properties for client side change tracking
    public interface IClientChangeTracking
    {
        // accepts changes made to the entity object
        void AcceptChanges();
        // rejects changes made to the entity object
        void RejectChanges();
        // whether the entity object has any changes
        bool HasChanges { get; }
        // accepts changes made to the entity object and all objects of its object graph
        void AcceptObjectGraphChanges();
        // rejects changes made to the entity object and all objects of its object graph
        void RejectObjectGraphChanges();
        // returns whether the entity object along with its object graph has any changes
        bool ObjectGraphHasChanges();
        // returns the estimate size of the entity object along with its object graph
        long EstimateObjectGraphSize();
        // returns the estimate size of the optimized entity object graph with only objects that have changes
        long EstimateObjectGraphChangeSize();
        // returns an optimized entity object graph with only objects that have changes
        IObjectWithChangeTracker GetObjectGraphChanges();
    }
    
    /// <summary>
    /// Interface IClientQuery( of T)
    /// </summary>
    /// <typeparam name="T">Expected type of the IClientQuery</typeparam>
    public interface IClientQuery<T>
    {
        ClientQuery AsClientQuery();
        ClientQuery<T> Include(string path);
        ClientQuery<T> OrderBy<TKey>(Expression<Func<T, TKey>> keySelector);
        ClientQuery<T> OrderByDescending<TKey>(Expression<Func<T, TKey>> keySelector);
        ClientQuery<T> Skip(int count);
        ClientQuery<T> Take(int count);
        ClientQuery<T> ThenBy<TKey>(Expression<Func<T, TKey>> keySelector);
        ClientQuery<T> ThenByDescending<TKey>(Expression<Func<T, TKey>> keySelector);
        ClientQuery<T> Where(Expression<Func<T, bool>> predicate);
    }
    
    /// <summary>
    /// Implementation of interface IClientQuery( of T)
    /// </summary>
    /// <typeparam name="T">Expected type of the ClientQuery</typeparam>
    public class ClientQuery<T> : IClientQuery<T>
    {
        #region Private Data Member
    
        private readonly ClientQueryInternal<T> _clientQueryInternal;
        private readonly Serializer _serializer;
        private readonly List<string> _includeList;
        private readonly XElement _xmlExpression;
    
        #endregion Private Data Member
    
        #region Constructor
    
        public ClientQuery()
        {
            _clientQueryInternal = new ClientQueryInternal<T>();
            _serializer = new Serializer();
            _includeList = new List<string>();
            _xmlExpression = _serializer.Serialize(_clientQueryInternal.Expression);
        }
    
        private ClientQuery(List<string> includeList, ClientQueryInternal<T> clientQueryInternal)
        {
            _clientQueryInternal = clientQueryInternal;
            _serializer = new Serializer();
            _includeList = includeList;
            _xmlExpression = _serializer.Serialize(_clientQueryInternal.Expression);
        }
    
        #endregion Constructor
    
        #region Interface IClientQuery<T> Implementation
    
        public ClientQuery AsClientQuery()
        {
            return new ClientQuery(_includeList, _xmlExpression);
        }
    
        public ClientQuery<T> Include(string path)
        {
            if (string.IsNullOrWhiteSpace(path)) throw new ArgumentException("Invalid path argument.");
            _includeList.Add(path);
            return new ClientQuery<T>(_includeList, _clientQueryInternal);
        }
    
        public ClientQuery<T> OrderBy<TKey>(Expression<Func<T, TKey>> keySelector)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(_clientQueryInternal.OrderBy(keySelector).Expression));
        }
    
        public ClientQuery<T> OrderByDescending<TKey>(Expression<Func<T, TKey>> keySelector)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(
                                          _clientQueryInternal.OrderByDescending(keySelector).Expression));
        }
    
        public ClientQuery<T> Skip(int count)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(_clientQueryInternal.Skip(count).Expression));
        }
    
        public ClientQuery<T> Take(int count)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(_clientQueryInternal.Take(count).Expression));
        }
    
        public ClientQuery<T> ThenBy<TKey>(Expression<Func<T, TKey>> keySelector)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(_clientQueryInternal.ThenBy(keySelector).Expression));
        }
    
        public ClientQuery<T> ThenByDescending<TKey>(Expression<Func<T, TKey>> keySelector)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(
                                          _clientQueryInternal.ThenByDescending(keySelector).Expression));
        }
    
        public ClientQuery<T> Where(Expression<Func<T, bool>> predicate)
        {
            return new ClientQuery<T>(_includeList,
                                      new ClientQueryInternal<T>(_clientQueryInternal.Where(predicate).Expression));
        }
    
        #endregion Interface IClientQuery<T> Implementation
    
        private class ClientQueryInternal<TChild> : IOrderedQueryable<TChild>
        {
            #region Private Data Member
    
            private readonly IQueryProvider _provider;
            private readonly Expression _expression;
    
            #endregion Private Data Member
    
            #region Constructor
    
            public ClientQueryInternal()
            {
                _provider = new List<TChild>().AsQueryable().Provider;
                _expression = Expression.Constant(this);
            }
    
            public ClientQueryInternal(Expression expression)
            {
                _provider = new List<TChild>().AsQueryable().Provider;
                _expression = expression;
            }
    
            #endregion Constructor
    
            #region IOrderedQueryable<TChild> Interface Implementation
    
            public IEnumerator<TChild> GetEnumerator()
            {
                return ((IEnumerable<TChild>) _provider.Execute(_expression)).GetEnumerator();
            }
    
            IEnumerator IEnumerable.GetEnumerator()
            {
                return ((IEnumerable) _provider.Execute(_expression)).GetEnumerator();
            }
    
            public Type ElementType
            {
                get { return typeof (TChild); }
            }
    
            public Expression Expression
            {
                get { return _expression; }
            }
    
            public IQueryProvider Provider
            {
                get { return _provider; }
            }
    
            #endregion IOrderedQueryable<TChild> Interface Implementation
        }
    }
    
    /// <summary>
    /// ClientQuerySet provides properties which we can use
    /// as data sources for client queries.
    /// </summary>
    public static class ClientQuerySet
    {
        #region ClientQuerySet Properties
    
        public static ClientQuery<Course> Courses
        {
            get { return new ClientQuery<Course>(); }
        }
    
        public static ClientQuery<Enrollment> Enrollments
        {
            get { return new ClientQuery<Enrollment>(); }
        }
    
        public static ClientQuery<Instructor> Instructors
        {
            get { return new ClientQuery<Instructor>(); }
        }
    
        public static ClientQuery<Person> People
        {
            get { return new ClientQuery<Person>(); }
        }
    
        public static ClientQuery<Student> Students
        {
            get { return new ClientQuery<Student>(); }
        }

        #endregion

    }
    
    internal class Serializer
    {
        #region Public Serialize Method
    
        public XElement Serialize(Expression e)
        {
            e = new ExpressionEvaluator().Evaluate(e);
            return GenerateXmlFromExpressionCore(e);
        }
    
        #endregion Public Serialize Method
    
        #region Private Serializer Method
    
        private XElement GenerateXmlFromExpressionCore(Expression e)
        {
            if (e == null) return null;
    
            if (e.NodeType == ExpressionType.Constant && typeof (IOrderedQueryable).IsAssignableFrom(e.Type))
            {
                var elementType = ((IOrderedQueryable) ((ConstantExpression) e).Value).ElementType;
                if (typeof (IOrderedQueryable<>).MakeGenericType(new[] {elementType})
                        .IsAssignableFrom(e.Type) && elementType.FullName != null)
                    return new XElement("ClientQuery",
                                        new XAttribute("elementType", elementType.FullName));
            }
    
            var binaryExpression = e as BinaryExpression;
            if (binaryExpression != null)
            {
                return BinaryExpressionToXElement(binaryExpression);
            }
            var conditionalExpression = e as ConditionalExpression;
            if (conditionalExpression != null)
            {
                return ConditionalExpressionToXElement(conditionalExpression);
            }
            var constantExpression = e as ConstantExpression;
            if (constantExpression != null)
            {
                return ConstantExpressionToXElement(constantExpression);
            }
            var invocationExpression = e as InvocationExpression;
            if (invocationExpression != null)
            {
                return InvocationExpressionToXElement(invocationExpression);
            }
            var lambdaExpression = e as LambdaExpression;
            if (lambdaExpression != null)
            {
                return LambdaExpressionToXElement(lambdaExpression);
            }
            var listInitExpression = e as ListInitExpression;
            if (listInitExpression != null)
            {
                return ListInitExpressionToXElement(listInitExpression);
            }
            var memberExpression = e as MemberExpression;
            if (memberExpression != null)
            {
                return MemberExpressionToXElement(memberExpression);
            }
            var memberInitExpression = e as MemberInitExpression;
            if (memberInitExpression != null)
            {
                return MemberInitExpressionToXElement(memberInitExpression);
            }
            var methodCallExpression = e as MethodCallExpression;
            if (methodCallExpression != null)
            {
                return MethodCallExpressionToXElement(methodCallExpression);
            }
            var newArrayExpression = e as NewArrayExpression;
            if (newArrayExpression != null)
            {
                return NewArrayExpressionToXElement(newArrayExpression);
            }
            var newExpression = e as NewExpression;
            if (newExpression != null)
            {
                return NewExpressionToXElement(newExpression);
            }
            var parameterExpression = e as ParameterExpression;
            if (parameterExpression != null)
            {
                return ParameterExpressionToXElement(parameterExpression);
            }
            var typeBinaryExpression = e as TypeBinaryExpression;
            if (typeBinaryExpression != null)
            {
                return TypeBinaryExpressionToXElement(typeBinaryExpression);
            }
            var unaryExpression = e as UnaryExpression;
            if (unaryExpression != null)
            {
                return UnaryExpressionToXElement(unaryExpression);
            }
            throw new NotSupportedException("Expression not supported.");
        }
    
        private XElement BinaryExpressionToXElement(BinaryExpression e)
        {
            var xElementValues = new object[6];
            xElementValues[0] = GenerateXmlFromExpression("Right", e.Right);
            xElementValues[1] = GenerateXmlFromExpression("Left", e.Left);
            xElementValues[2] = GenerateXmlFromMethodInfo("Method", e.Method);
            xElementValues[3] = GenerateXmlFromExpression("Conversion", e.Conversion);
            xElementValues[4] = GenerateXmlWithDataContractSerializer(typeof (bool), "IsLiftedToNull", e.IsLiftedToNull);
            xElementValues[5] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("BinaryExpression", xElementValues);
        }
    
        private XElement ConditionalExpressionToXElement(ConditionalExpression e)
        {
            var xElementValues = new object[5];
            xElementValues[0] = GenerateXmlFromExpression("Test", e.Test);
            xElementValues[1] = GenerateXmlFromExpression("IfTrue", e.IfTrue);
            xElementValues[2] = GenerateXmlFromExpression("IfFalse", e.IfFalse);
            xElementValues[3] = GenerateXmlFromType("Type", e.Type);
            xElementValues[4] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("ConditionalExpression", xElementValues);
        }
    
        private XElement ConstantExpressionToXElement(ConstantExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlWithDataContractSerializer(e.Type, "Value", e.Value);
            xElementValues[1] = GenerateXmlFromType("Type", e.Type);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("ConstantExpression", xElementValues);
        }
    
        private XElement InvocationExpressionToXElement(InvocationExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromExpression("Expression", e.Expression);
            xElementValues[1] = GenerateXmlFromExpressionList("Arguments", e.Arguments);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("InvocationExpression", xElementValues);
        }
    
        private XElement LambdaExpressionToXElement(LambdaExpression e)
        {
            var xElementValues = new object[6];
            xElementValues[0] = GenerateXmlFromType("Type", e.Type);
            xElementValues[1] = GenerateXmlFromExpression("Body", e.Body);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (string), "Name", e.Name);
            xElementValues[3] = GenerateXmlWithDataContractSerializer(typeof (bool), "TailCall", e.TailCall);
            xElementValues[4] = GenerateXmlFromExpressionList("Parameters", AsIEnumerableOf<Expression>(e.Parameters));
            xElementValues[5] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("LambdaExpression", xElementValues);
        }
    
        private XElement ListInitExpressionToXElement(ListInitExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromExpression("NewExpression", e.NewExpression);
            xElementValues[1] = GenerateXmlFromElementInitList("Initializers", e.Initializers);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("ListInitExpression", xElementValues);
        }
    
        private XElement MemberExpressionToXElement(MemberExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromExpression("Expression", e.Expression);
            xElementValues[1] = GenerateXmlFromMemberInfo(typeof (MemberInfo), "Member", e.Member);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("MemberExpression", xElementValues);
        }
    
        private XElement MemberInitExpressionToXElement(MemberInitExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromExpression("NewExpression", e.NewExpression);
            xElementValues[1] = GenerateXmlFromMemberBindingList("Bindings", e.Bindings);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("MemberInitExpression", xElementValues);
        }
    
        private XElement MethodCallExpressionToXElement(MethodCallExpression e)
        {
            var xElementValues = new object[4];
            xElementValues[0] = GenerateXmlFromExpression("Object", e.Object);
            xElementValues[1] = GenerateXmlFromMethodInfo("Method", e.Method);
            xElementValues[2] = GenerateXmlFromExpressionList("Arguments", e.Arguments);
            xElementValues[3] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("MethodCallExpression", xElementValues);
        }
    
        private XElement NewArrayExpressionToXElement(NewArrayExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromType("Type", e.Type);
            xElementValues[1] = GenerateXmlFromExpressionList("Expressions", e.Expressions);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("NewArrayExpression", xElementValues);
        }
    
        private XElement NewExpressionToXElement(NewExpression e)
        {
            var xElementValues = new object[4];
            xElementValues[0] = GenerateXmlFromConstructorInfo("Constructor", e.Constructor);
            xElementValues[1] = GenerateXmlFromExpressionList("Arguments", e.Arguments);
            xElementValues[2] = GenerateXmlFromMemberInfoList("Members", e.Members);
            xElementValues[3] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("NewExpression", xElementValues);
        }
    
        private XElement ParameterExpressionToXElement(ParameterExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromType("Type", e.Type);
            xElementValues[1] = GenerateXmlWithDataContractSerializer(typeof (string), "Name", e.Name);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("ParameterExpression", xElementValues);
        }
    
        private XElement TypeBinaryExpressionToXElement(TypeBinaryExpression e)
        {
            var xElementValues = new object[3];
            xElementValues[0] = GenerateXmlFromExpression("Expression", e.Expression);
            xElementValues[1] = GenerateXmlFromType("TypeOperand", e.TypeOperand);
            xElementValues[2] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("TypeBinaryExpression", xElementValues);
        }
    
        private XElement UnaryExpressionToXElement(UnaryExpression e)
        {
            var xElementValues = new object[4];
            xElementValues[0] = GenerateXmlFromExpression("Operand", e.Operand);
            xElementValues[1] = GenerateXmlFromType("Type", e.Type);
            xElementValues[2] = GenerateXmlFromMethodInfo("Method", e.Method);
            xElementValues[3] = GenerateXmlWithDataContractSerializer(typeof (ExpressionType), "NodeType", e.NodeType);
            return new XElement("UnaryExpression", xElementValues);
        }
    
        #endregion Private Serializer Method
    
        #region Private Serializer Helper Method
    
        private XElement GenerateXmlWithDataContractSerializer(Type propType, string propName, object value)
        {
            using (var stream = new MemoryStream())
            using (var reader = new StreamReader(stream, Encoding.UTF8))
            {
                var serializer = new DataContractSerializer(propType);
                serializer.WriteObject(stream, value);
                stream.Seek(0, SeekOrigin.Begin);
                return new XElement(propName, reader.ReadToEnd());
            }
        }
    
        private XElement GenerateXmlFromConstructorInfo(string propName, ConstructorInfo constructorInfo)
        {
            return constructorInfo == null
                       ? new XElement(propName)
                       : new XElement(propName,
                                      new XAttribute("MemberType", constructorInfo.MemberType),
                                      new XAttribute("MethodName", constructorInfo.Name),
                                      GenerateXmlFromType("DeclaringType", constructorInfo.DeclaringType),
                                      new XElement("Parameters",
                                                   from param in constructorInfo.GetParameters()
                                                   select new XElement("Parameter",
                                                                       new XAttribute("Name", param.Name),
                                                                       GenerateXmlFromType("Type", param.ParameterType))));
        }
    
        private XElement GenerateXmlFromElementInit(ElementInit elementInit)
        {
            return new XElement("ElementInit",
                                GenerateXmlFromMethodInfo("AddMethod", elementInit.AddMethod),
                                GenerateXmlFromExpressionList("Arguments", elementInit.Arguments));
        }
    
        private XElement GenerateXmlFromExpression(string propName, Expression e)
        {
            return new XElement(propName, GenerateXmlFromExpressionCore(e));
        }
    
        private XElement GenerateXmlFromFieldInfo(string propName, FieldInfo fieldInfo)
        {
            return fieldInfo == null
                       ? new XElement(propName)
                       : new XElement(propName,
                                      new XAttribute("MemberType", fieldInfo.MemberType),
                                      new XAttribute("FieldName", fieldInfo.Name),
                                      GenerateXmlFromType("DeclaringType", fieldInfo.DeclaringType));
        }
    
        private XElement GenerateXmlFromMemberAssignment(MemberAssignment memberAssignment)
        {
            return new XElement("MemberAssignment",
                                GenerateXmlFromMemberInfo(memberAssignment.Member.GetType(), "Member",
                                                          memberAssignment.Member),
                                GenerateXmlFromExpression("Expression", memberAssignment.Expression));
        }
    
        private XElement GenerateXmlFromMemberBinding(MemberBinding binding)
        {
            switch (binding.BindingType)
            {
                case MemberBindingType.Assignment:
                    return GenerateXmlFromMemberAssignment(binding as MemberAssignment);
                case MemberBindingType.ListBinding:
                    return GenerateXmlFromMemberListBinding(binding as MemberListBinding);
                case MemberBindingType.MemberBinding:
                    return GenerateXmlFromMemberMemberBinding(binding as MemberMemberBinding);
                default:
                    throw new NotSupportedException(string.Format("Binding type {0} not supported.", binding.BindingType));
            }
        }
    
        private XElement GenerateXmlFromMemberListBinding(MemberListBinding memberListBinding)
        {
            return new XElement("MemberListBinding",
                                GenerateXmlFromMemberInfo(memberListBinding.Member.GetType(), "Member",
                                                          memberListBinding.Member),
                                GenerateXmlFromElementInitList("Initializers", memberListBinding.Initializers));
        }
    
        private XElement GenerateXmlFromMemberMemberBinding(MemberMemberBinding memberMemberBinding)
        {
            return new XElement("MemberMemberBinding",
                                GenerateXmlFromMemberInfo(memberMemberBinding.Member.GetType(), "Member",
                                                          memberMemberBinding.Member),
                                GenerateXmlFromMemberBindingList("Bindings", memberMemberBinding.Bindings));
        }
    
        private XElement GenerateXmlFromMemberInfo(Type propType, string propName, MemberInfo value)
        {
            if (propType == typeof (ConstructorInfo) || value is ConstructorInfo)
                return GenerateXmlFromConstructorInfo(propName, value as ConstructorInfo);
            if (propType == typeof (FieldInfo) || value is FieldInfo)
                return GenerateXmlFromFieldInfo(propName, value as FieldInfo);
            if (propType == typeof (MethodInfo) || value is MethodInfo)
                return GenerateXmlFromMethodInfo(propName, value as MethodInfo);
            if (propType == typeof (PropertyInfo) || value is PropertyInfo)
                return GenerateXmlFromPropertyInfo(propName, value as PropertyInfo);
    
            throw new NotSupportedException(propName);
        }
    
        private XElement GenerateXmlFromMethodInfo(string propName, MethodInfo methodInfo)
        {
            return methodInfo == null
                       ? new XElement(propName)
                       : new XElement(propName,
                                      new XAttribute("MemberType", methodInfo.MemberType),
                                      new XAttribute("MethodName", methodInfo.Name),
                                      GenerateXmlFromType("DeclaringType", methodInfo.DeclaringType),
                                      new XElement("Parameters",
                                                   from param in methodInfo.GetParameters()
                                                   select GenerateXmlFromType("Type", param.ParameterType)),
                                      new XElement("GenericArgTypes",
                                                   from argType in methodInfo.GetGenericArguments()
                                                   select GenerateXmlFromType("Type", argType)));
        }
    
        private XElement GenerateXmlFromPropertyInfo(string propName, PropertyInfo propertyInfo)
        {
            return propertyInfo == null
                       ? new XElement(propName)
                       : new XElement(propName,
                                      new XAttribute("MemberType", propertyInfo.MemberType),
                                      new XAttribute("PropertyName", propertyInfo.Name),
                                      GenerateXmlFromType("DeclaringType", propertyInfo.DeclaringType),
                                      new XElement("IndexParameters",
                                                   from param in propertyInfo.GetIndexParameters()
                                                   select GenerateXmlFromType("Type", param.ParameterType)));
        }
    
        private XElement GenerateXmlFromType(string propName, Type type)
        {
            return new XElement(propName, GenerateXmlFromTypeCore(type));
        }
    
        private XElement GenerateXmlFromElementInitList(string propName, IEnumerable<ElementInit> initializers)
        {
            if (initializers == null)
                initializers = new ElementInit[] {};
            return new XElement(propName,
                                from elementInit in initializers
                                select GenerateXmlFromElementInit(elementInit));
        }
    
        private XElement GenerateXmlFromExpressionList(string propName, IEnumerable<Expression> expressions)
        {
            return new XElement(propName,
                                from expression in expressions
                                select GenerateXmlFromExpressionCore(expression));
        }
    
        private XElement GenerateXmlFromMemberBindingList(string propName, IEnumerable<MemberBinding> bindings)
        {
            if (bindings == null)
                bindings = new MemberBinding[] {};
            return new XElement(propName,
                                from binding in bindings
                                select GenerateXmlFromMemberBinding(binding));
        }
    
        private XElement GenerateXmlFromMemberInfoList(string propName, IEnumerable<MemberInfo> members)
        {
            if (members == null)
                members = new MemberInfo[] {};
            return new XElement(propName,
                                from member in members
                                select GenerateXmlFromMemberInfo(member.GetType(), "Info", member));
        }
    
        private XElement GenerateXmlFromTypeCore(Type type)
        {
            // add detection of VB anon types
            if (type.Name.StartsWith("<>f__") || type.Name.StartsWith("VB$AnonymousType"))
                return new XElement("AnonymousType",
                                    new XAttribute("Name", type.FullName ?? string.Empty),
                                    from property in type.GetProperties()
                                    select new XElement("Property",
                                                        new XAttribute("Name", property.Name),
                                                        GenerateXmlFromTypeCore(property.PropertyType)),
                                    new XElement("Constructor",
                                                 from parameter in type.GetConstructors().First().GetParameters()
                                                 select new XElement("Parameter",
                                                                     new XAttribute("Name", parameter.Name),
                                                                     GenerateXmlFromTypeCore(parameter.ParameterType))
                                        ));
            // GetGenericArguments returns args for nongeneric types 
            if (type.IsGenericType)
            {
                return new XElement("Type",
                                    new XAttribute("Name", type.GetGenericTypeDefinition().FullName ?? string.Empty),
                                    from genArgType in type.GetGenericArguments()
                                    select GenerateXmlFromTypeCore(genArgType));
            }
            return new XElement("Type", new XAttribute("Name", type.FullName ?? string.Empty));
        }
    
        private IEnumerable<T> AsIEnumerableOf<T>(object value)
        {
            return value == null ? null : (value as IEnumerable).Cast<T>();
        }
    
        #endregion Private Serializer Helper Method
    }
    
    internal sealed class ExpressionEvaluator : ExpressionVisitor
    {
        #region Private Data Member
    
        private HashSet<Expression> _subTrees = new HashSet<Expression>();
        private bool _initializeSubTrees;
        private bool _hasParameter;
    
        #endregion Private Data Member
    
        #region Public Method
    
        public Expression Evaluate(Expression expression)
        {
            _subTrees = new HashSet<Expression>();
            _initializeSubTrees = true;
            Visit(expression);
            _initializeSubTrees = false;
            return Visit(expression);
        }
    
        #endregion Public Method
    
        #region Visit Override
    
        public override Expression Visit(Expression expression)
        {
            return _initializeSubTrees ? InitializeSubTrees(expression) : VisitSubTrees(expression);
        }
    
        private Expression InitializeSubTrees(Expression expression)
        {
            if (expression != null)
            {
                var hasParameter = _hasParameter;
                _hasParameter = false;
                base.Visit(expression);
    
                if (!_hasParameter)
                {
                    if (expression.NodeType != ExpressionType.Parameter)
                    {
                        if (expression.NodeType != ExpressionType.Constant &&
                            expression.NodeType != ExpressionType.Lambda)
                        {
                            _subTrees.Add(expression);
                        }
                    }
                    else
                        _hasParameter = true;
                }
                _hasParameter |= hasParameter;
            }
            return expression;
        }
    
        private Expression VisitSubTrees(Expression expression)
        {
            if (expression == null)
            {
                return null;
            }
            if (_subTrees.Contains(expression))
            {
                var lambda = Expression.Lambda(expression);
                var delegateFunction = lambda.Compile();
                var result = delegateFunction.DynamicInvoke(null);
                return Expression.Constant(result, expression.Type);
            }
            return base.Visit(expression);
        }
    
        #endregion Visit Override
    }
}
#endif

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)
United States United States
Weidong has been an information system professional since 1990. He has a Master's degree in Computer Science, and is currently a MCSD .NET

Comments and Discussions