Click here to Skip to main content
15,896,606 members
Articles / Desktop Programming / WPF

The WPF-NHibernate Toolkit

Rate me:
Please Sign up or sign in to vote.
4.98/5 (23 votes)
16 Jan 2010CPOL28 min read 160.1K   3.3K   114  
Adapt NHibernate classes to run in WPF
using System;
using System.Reflection;

namespace VmWrapperExpress.DomainModel
{
    public class PropertySpecDM : DomainBase
    {
        #region Constructor

        public PropertySpecDM(PropertyInfo propertyInfo) : base(propertyInfo.Name)
        {
            this.Initialize(propertyInfo);
        }

        #endregion

        #region Properties

        /// <summary>
        /// The 'friendly' type of the collection in a collection property. Null otherwise.
        /// </summary>
        public string FriendlyCollectionType { get; set; }

        /// <summary>
        /// The 'friendly' type of the elements in a collection property. Null otherwise.
        /// </summary>
        public string FriendlyElementType { get; set; }

        /// <summary>
        /// The 'friendly' type name of the property.
        /// </summary>
        /// <remarks>This property replaces .NET's native 
        /// collection notation with angle brackets.</remarks>
        public string FriendlyType { get; set; }

        /// <summary>
        /// The full type of the collection in a collection property. Null otherwise.
        /// </summary>
        public string FullCollectionType { get; set; }

        /// <summary>
        /// The full type of the elements in a collection property. Null otherwise.
        /// </summary>
        public string FullElementType { get; set; }

        /// <summary>
        /// The full type name of the property.
        /// </summary>
        public string FullType { get; set; }

        /// <summary>
        /// Whether this property is a collection.
        /// </summary>
        public bool IsCollection { get; set; }

        /// <summary>
        /// Whether the type of this property is a domain class type.
        /// </summary>
        public bool IsDomainClassType { get; set; }

        /// <summary>
        /// Whether this property is selected for inclusion in the ViewModel.
        /// </summary>
        public bool IsSelected { get; set; }

        /// <summary>
        /// The type and name of this property.
        /// </summary>
        public string Profile
        {
            get { return String.Format("({0}) {1}", this.FriendlyType, this.Name); }
        }

        #endregion

        #region Overrides

        public override string ToString()
        {
            return this.Profile;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Determines whether a raw or friendly property is a collection.
        /// </summary>
        /// <param name="propertyType">The name of the property type.</param>
        /// <returns>True if the property is a collection; false otherwise. </returns>
        private bool GetIsCollection(string propertyType)
        {
            // Initialize
            var isCollection = false;

            // Raw property type
            if (propertyType.Contains("`1[")) isCollection = true;

                // Friendly property type
            else if (propertyType.Contains("<")) isCollection = true;

            // Set return value
            return isCollection;
        }

        /// <summary>
        /// Replaces a .NET system type with a C# type
        /// </summary>
        /// <param name="propertyType">The .NET property type to be replaced.</param>
        /// <returns>The C# type corresponding to the .NET type passed in, if any; otherwise, the original .NET type.</returns>
        private string GetCSharpType(string propertyType)
        {
            var result = propertyType;
            switch (propertyType)
            {
                case "System.Boolean":
                    result = "bool";
                    break;

                case "System.Byte":
                    result = "byte";
                    break;

                case "System.SByte":
                    result = "sbyte";
                    break;

                case "System.Char":
                    result = "char";
                    break;

                case "System.Decimal":
                    result = "decimal";
                    break;

                case "System.Double":
                    result = "double";
                    break;

                case "System.Single":
                    result = "single";
                    break;

                case "System.Int32":
                    result = "int";
                    break;

                case "System.Object":
                    result = "object";
                    break;

                case "System.String":
                    result = "string";
                    break;
            }

            // Set return value
            return result;
        }

        /// <summary>
        /// Gets the 'friendly' counterpart of a .NET type.
        /// </summary>
        /// <param name="propertyType">The .NET type to be converted.</param>
        /// <returns>The 'friendly' version of the type name.</returns>
        /// <remarks>Friendly type names use angle brackets in collections,
        /// instead of the .NET system signature, use C# types instead of
        /// .NET system types, and have namespaces stripped out.</remarks>
        private string GetFriendlyType(string propertyType)
        {
            // Initialize
            var friendlyType = propertyType;
            var isCollection = this.GetIsCollection(friendlyType);

            // Process collection property
            if (isCollection)
            {
                // Swap angle brackets for .NET collection signature
                friendlyType = friendlyType.Replace("`1[", "<");
                friendlyType = friendlyType.Replace("]", ">");

                // Parse property into collection and element types
                var c = new[] {'<'};
                var s = friendlyType.Split(c);
                var collectionType = s[0];
                var elementType = s[1].Replace(">", String.Empty);

                // Swap .NET element type for C# type, if avalable
                friendlyType = this.GetCSharpType(friendlyType);

                // Strip namespaces from both types
                collectionType = this.StripNamespace(collectionType);
                elementType = this.StripNamespace(elementType);

                // Reassemble collection property
                friendlyType = String.Format("{0}<{1}>", collectionType, elementType);
            }

                // Process simple property
            else
            {
                // Swap C# type. for NET property type, if avalable
                friendlyType = this.GetCSharpType(friendlyType);

                // Strip namespace from property type
                friendlyType = this.StripNamespace(friendlyType);
            }

            // Set return value
            return friendlyType;
        }

        /// <summary>
        /// Initializes this object.
        /// </summary>
        /// <param name="propertyInfo">A System.Reflection. PropertyInfo object for the property represented by this object.</param>
        private void Initialize(PropertyInfo propertyInfo)
        {
            /* Note that we set the IsDomainClassType property
             * in the AssemblySpecDM.Initialize() method. */

            /* The raw property type is for type comparisons; 
             * the friendly property type is for UI display. */

            // Set general properties
            this.FullType = propertyInfo.PropertyType.ToString();
            this.FriendlyType = this.GetFriendlyType(this.FullType);
            this.IsCollection = this.GetIsCollection(FriendlyType);
            this.IsSelected = false;

            // Set friendly type for simple property
            if (! this.IsCollection)
            {
                this.FriendlyType = this.GetFriendlyType(this.FullType);
            }

            // Set collection properties
            if (this.IsCollection)
            {
                // Parse property type into collection and element types
                var collectionType = String.Empty;
                var elementType = String.Empty;
                this.ParseCollectionProperty(this.FullType, ref collectionType, ref elementType);

                // Get 'full' types
                this.FullCollectionType = collectionType;
                this.FullElementType = elementType;

                // Get 'friendly' types
                this.FriendlyCollectionType = this.GetFriendlyType(collectionType);
                this.FriendlyElementType = this.GetFriendlyType(elementType);

                // Assemble friendly type for entire property
                this.FriendlyType = String.Format("{0}<{1}>", this.FriendlyCollectionType, this.FriendlyElementType);
            }
        }

        /// <summary>
        /// Parses a 'friendly' collection property type into collection and element types.
        /// </summary>
        /// <param name="fullType">The full type name.</param>
        /// <param name="collectionType">The collection type of the property.</param>
        /// <param name="elementType">The element type of the property.</param>
        private void ParseCollectionProperty(string fullType, ref string collectionType, ref string elementType)
        {
            // Split type into collection and element types
            var c = new [] {'`'};
            var s = fullType.Split(c);
            collectionType = s[0];
            s[1] = s[1].Replace("1[", String.Empty);
            elementType = s[1].Replace("]", String.Empty);
        }

        /// <summary>
        /// Strips the namespace from a type declaration.
        /// </summary>
        /// <param name="propertyType">The property type declaration.</param>
        /// <returns>The type declaration, without the namespace.</returns>
        private string StripNamespace(string propertyType)
        {
            var c = new [] {'.'};
            var s = propertyType.Split(c);
            var result = s[s.Length - 1];

            // Set return value
            return result;
        }

        #endregion
    }
}

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) Foresight Systems
United States United States
David Veeneman is a financial planner and software developer. He is the author of "The Fortune in Your Future" (McGraw-Hill 1998). His company, Foresight Systems, develops planning and financial software.

Comments and Discussions