Business Logic Toolkit for .NET
www.bltoolkit.net
|  Home   |  Download   |  Documentation   |  Discussions   |  License   |

  Source.Reflection.Emit.TypeBuilderHelper.cs

 
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;

namespace BLToolkit.Reflection.Emit
{
    using TypeBuilder.Builders;

    /// <summary>
    /// A wrapper around the <see cref="TypeBuilder"/> class.
    /// </summary>
    /// <include file="Examples.CS.xml" path='examples/emit[@name="Emit"]/*' />
    /// <include file="Examples.VB.xml" path='examples/emit[@name="Emit"]/*' />
    /// <seealso cref="System.Reflection.Emit.TypeBuilder">TypeBuilder Class</seealso>
    public class TypeBuilderHelper
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TypeBuilderHelper"/> class
        /// with the specified parameters.
        /// </summary>
        /// <param name="assemblyBuilder">Associated <see cref="AssemblyBuilderHelper"/>.</param>
        /// <param name="typeBuilder">A <see cref="TypeBuilder"/></param>
        public TypeBuilderHelper(AssemblyBuilderHelper assemblyBuilder, System.Reflection.Emit.TypeBuilder typeBuilder)
        {
            if (assemblyBuilder == null) throw new ArgumentNullException("assemblyBuilder");
            if (typeBuilder     == null) throw new ArgumentNullException("typeBuilder");

            _assembly    = assemblyBuilder;
            _typeBuilder = typeBuilder;

            _typeBuilder.SetCustomAttribute(_assembly.BLToolkitAttribute);
        }

        private readonly AssemblyBuilderHelper _assembly;
        /// <summary>
        /// Gets associated <see cref="AssemblyBuilderHelper"/>.
        /// </summary>
        public  AssemblyBuilderHelper  Assembly
        {
            get { return _assembly; }
        }

        private readonly System.Reflection.Emit.TypeBuilder _typeBuilder;
        /// <summary>
        /// Gets <see cref="System.Reflection.Emit.TypeBuilder"/>.
        /// </summary>
        public  System.Reflection.Emit.TypeBuilder  TypeBuilder
        {
            get { return _typeBuilder; }
        }

        /// <summary>
        /// Converts the supplied <see cref="TypeBuilderHelper"/> to a <see cref="TypeBuilder"/>.
        /// </summary>
        /// <param name="typeBuilder">The <see cref="TypeBuilderHelper"/>.</param>
        /// <returns>A <see cref="TypeBuilder"/>.</returns>
        public static implicit operator System.Reflection.Emit.TypeBuilder(TypeBuilderHelper typeBuilder)
        {
            if (typeBuilder == null) throw new ArgumentNullException("typeBuilder");

            return typeBuilder.TypeBuilder;
        }

        #region DefineMethod Overrides

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <param name="returnType">The return type of the method.</param>
        /// <param name="parameterTypes">The types of the parameters of the method.</param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(
            string name, MethodAttributes attributes, Type returnType, params Type[] parameterTypes)
        {
            return new MethodBuilderHelper(this, _typeBuilder.DefineMethod(name, attributes, returnType, parameterTypes));
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <param name="callingConvention">The <see cref="CallingConventions">calling convention</see> of the method.</param>
        /// <param name="returnType">The return type of the method.</param>
        /// <param name="parameterTypes">The types of the parameters of the method.</param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(
            string             name,
            MethodAttributes   attributes,
            CallingConventions callingConvention,
            Type               returnType,
            Type[]             parameterTypes)
        {
            return new MethodBuilderHelper(this, _typeBuilder.DefineMethod(
                name, attributes, callingConvention, returnType, parameterTypes));
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <param name="returnType">The return type of the method.</param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(string name, MethodAttributes attributes, Type returnType)
        {
            return new MethodBuilderHelper(
                this,
                _typeBuilder.DefineMethod(name, attributes, returnType, Type.EmptyTypes));
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(string name, MethodAttributes attributes)
        {
            return new MethodBuilderHelper(
                this,
                _typeBuilder.DefineMethod(name, attributes, typeof(void), Type.EmptyTypes));
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <returns>The defined method.</returns>
        /// <param name="callingConvention">The calling convention of the method.</param>
        public MethodBuilderHelper DefineMethod(
            string             name,
            MethodAttributes   attributes,
            CallingConventions callingConvention)
        {
            return new MethodBuilderHelper(
                this,
                _typeBuilder.DefineMethod(name, attributes, callingConvention));
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <param name="callingConvention">The <see cref="CallingConventions">calling convention</see> of the method.</param>
        /// <param name="genericArguments">Generic arguments of the method.</param>
        /// <param name="returnType">The return type of the method.</param>
        /// <param name="parameterTypes">The types of the parameters of the method.</param>
        /// <returns>The defined generic method.</returns>
        public MethodBuilderHelper DefineGenericMethod(
            string             name,
            MethodAttributes   attributes,
            CallingConventions callingConvention,
            Type[]             genericArguments,
            Type               returnType,
            Type[]             parameterTypes)
        {
            return new MethodBuilderHelper(
                this,
                _typeBuilder.DefineMethod(name, attributes, callingConvention), genericArguments, returnType, parameterTypes);
        }


        private Dictionary<MethodInfo, MethodBuilder> _overriddenMethods;

        /// <summary>
        /// Retrieves the map of base type methods overridden by this type.
        /// </summary>
        public  Dictionary<MethodInfo, MethodBuilder>  OverriddenMethods
        {
            get { return _overriddenMethods ?? (_overriddenMethods = new Dictionary<MethodInfo,MethodBuilder>()); }
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param>
        /// <param name="attributes">The attributes of the method. </param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(
            string           name,
            MethodInfo       methodInfoDeclaration,
            MethodAttributes attributes)
        {
            if (methodInfoDeclaration == null) throw new ArgumentNullException("methodInfoDeclaration");

            MethodBuilderHelper method;
            ParameterInfo[]     pi         = methodInfoDeclaration.GetParameters();
            Type[]              parameters = new Type[pi.Length];

            for (int i = 0; i < pi.Length; i++)
                parameters[i] = pi[i].ParameterType;

            if (methodInfoDeclaration.ContainsGenericParameters)
            {
                method = DefineGenericMethod(
                    name,
                    attributes,
                    methodInfoDeclaration.CallingConvention,
                    methodInfoDeclaration.GetGenericArguments(),
                    methodInfoDeclaration.ReturnType,
                    parameters);
            }
            else
            {
                method = DefineMethod(
                    name,
                    attributes,
                    methodInfoDeclaration.CallingConvention,
                    methodInfoDeclaration.ReturnType,
                    parameters);
            }

            // Compiler overrides methods only for interfaces. We do the same.
            // If we wanted to override virtual methods, then methods should've had
            // MethodAttributes.VtableLayoutMask attribute
            // and the following condition should've been used below:
            // if ((methodInfoDeclaration is FakeMethodInfo) == false)
            //
            if (methodInfoDeclaration.DeclaringType.IsInterface && !(methodInfoDeclaration is FakeMethodInfo))
            {
                OverriddenMethods.Add(methodInfoDeclaration, method.MethodBuilder);
                _typeBuilder.DefineMethodOverride(method.MethodBuilder, methodInfoDeclaration);
            }

            method.OverriddenMethod = methodInfoDeclaration;

            for (int i = 0; i < pi.Length; i++)
                method.MethodBuilder.DefineParameter(i + 1, pi[i].Attributes, pi[i].Name);

            return method;
        }

        /// <summary>
        /// Adds a new method to the class, with the given name and method signature.
        /// </summary>
        /// <param name="name">The name of the method. name cannot contain embedded nulls. </param>
        /// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(string name, MethodInfo methodInfoDeclaration)
        {
            return DefineMethod(name, methodInfoDeclaration, MethodAttributes.Virtual);
        }

        /// <summary>
        /// Adds a new private method to the class.
        /// </summary>
        /// <param name="methodInfoDeclaration">The method whose declaration is to be used.</param>
        /// <returns>The defined method.</returns>
        public MethodBuilderHelper DefineMethod(MethodInfo methodInfoDeclaration)
        {
            if (methodInfoDeclaration == null) throw new ArgumentNullException("methodInfoDeclaration");

            bool isInterface = methodInfoDeclaration.DeclaringType.IsInterface;
            bool isFake      = methodInfoDeclaration is FakeMethodInfo;

            string name = isInterface && !isFake?
                methodInfoDeclaration.DeclaringType.FullName + "." + methodInfoDeclaration.Name:
                methodInfoDeclaration.Name;

            MethodAttributes attributes = 
                MethodAttributes.Virtual |
                MethodAttributes.HideBySig |
                MethodAttributes.PrivateScope |
                methodInfoDeclaration.Attributes & MethodAttributes.SpecialName;

            if (isInterface && !isFake)
                attributes |= MethodAttributes.Private;
            else if ((attributes & MethodAttributes.SpecialName) != 0)
                attributes |= MethodAttributes.Public;
            else
                attributes |= methodInfoDeclaration.Attributes & 
                    (MethodAttributes.Public | MethodAttributes.Private);

            return DefineMethod(name, methodInfoDeclaration, attributes);
        }

        #endregion

        /// <summary>
        /// Creates a Type object for the class.
        /// </summary>
        /// <returns>Returns the new Type object for this class.</returns>
        public Type Create()
        {
            return TypeBuilder.CreateType();
        }

        /// <summary>
        /// Sets a custom attribute using a custom attribute type.
        /// </summary>
        /// <param name="attributeType">Attribute type.</param>
        public void SetCustomAttribute(Type attributeType)
        {
            if (attributeType == null) throw new ArgumentNullException("attributeType");

            ConstructorInfo        ci        = attributeType.GetConstructor(Type.EmptyTypes);
            CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(ci, new object[0]);

            _typeBuilder.SetCustomAttribute(caBuilder);
        }

        /// <summary>
        /// Sets a custom attribute using a custom attribute type
        /// and named properties.
        /// </summary>
        /// <param name="attributeType">Attribute type.</param>
        /// <param name="properties">Named properties of the custom attribute.</param>
        /// <param name="propertyValues">Values for the named properties of the custom attribute.</param>
        public void SetCustomAttribute(
            Type           attributeType,
            PropertyInfo[] properties,
            object[]       propertyValues)
        {
            if (attributeType == null) throw new ArgumentNullException("attributeType");

            ConstructorInfo        ci        = attributeType.GetConstructor(Type.EmptyTypes);
            CustomAttributeBuilder caBuilder = new CustomAttributeBuilder(
                ci, new object[0], properties, propertyValues);

            _typeBuilder.SetCustomAttribute(caBuilder);
        }

        /// <summary>
        /// Sets a custom attribute using a custom attribute type
        /// and named property.
        /// </summary>
        /// <param name="attributeType">Attribute type.</param>
        /// <param name="propertyName">A named property of the custom attribute.</param>
        /// <param name="propertyValue">Value for the named property of the custom attribute.</param>
        public void SetCustomAttribute(
            Type   attributeType,
            string propertyName,
            object propertyValue)
        {
            SetCustomAttribute(
                attributeType,
                new PropertyInfo[] { attributeType.GetProperty(propertyName) },
                new object[]       { propertyValue } );
        }

        private ConstructorBuilderHelper _typeInitializer;
        /// <summary>
        /// Gets the initializer for this type.
        /// </summary>
        public ConstructorBuilderHelper TypeInitializer
        {
            get 
            {
                if (_typeInitializer == null)
                    _typeInitializer = new ConstructorBuilderHelper(this, _typeBuilder.DefineTypeInitializer());

                return _typeInitializer;
            }
        }

        /// <summary>
        /// Returns true if the initializer for this type has a body.
        /// </summary>
        public bool IsTypeInitializerDefined
        {
            get { return _typeInitializer != null; }
        }

        private ConstructorBuilderHelper _defaultConstructor;
        /// <summary>
        /// Gets the default constructor for this type.
        /// </summary>
        public  ConstructorBuilderHelper  DefaultConstructor
        {
            get 
            {
                if (_defaultConstructor == null)
                {
                    ConstructorBuilder builder = _typeBuilder.DefineConstructor(
                        MethodAttributes.Public,
                        CallingConventions.Standard,
                        Type.EmptyTypes);

                    _defaultConstructor = new ConstructorBuilderHelper(this, builder);
                }

                return _defaultConstructor;
            }
        }

        /// <summary>
        /// Returns true if the default constructor for this type has a body.
        /// </summary>
        public bool IsDefaultConstructorDefined
        {
            get { return _defaultConstructor != null; }
        }

        private ConstructorBuilderHelper _initConstructor;
        /// <summary>
        /// Gets the init context constructor for this type.
        /// </summary>
        public  ConstructorBuilderHelper  InitConstructor
        {
            get 
            {
                if (_initConstructor == null)
                {
                    ConstructorBuilder builder = _typeBuilder.DefineConstructor(
                        MethodAttributes.Public, 
                        CallingConventions.Standard,
                        new Type[] { typeof(InitContext) });

                    _initConstructor = new ConstructorBuilderHelper(this, builder);
                }

                return _initConstructor;
            }
        }

        /// <summary>
        /// Returns true if a constructor with parameter of <see cref="InitContext"/> for this type has a body.
        /// </summary>
        public bool IsInitConstructorDefined
        {
            get { return _initConstructor != null; }
        }

        /// <summary>
        /// Adds a new field to the class, with the given name, attributes and field type.
        /// </summary>
        /// <param name="fieldName">The name of the field. <paramref name="fieldName"/> cannot contain embedded nulls.</param>
        /// <param name="type">The type of the field.</param>
        /// <param name="attributes">The attributes of the field.</param>
        /// <returns>The defined field.</returns>
        public FieldBuilder DefineField(
            string          fieldName,
            Type            type,
            FieldAttributes attributes)
        {
            return _typeBuilder.DefineField(fieldName, type, attributes);
        }

        #region DefineConstructor Overrides

        /// <summary>
        /// Adds a new public constructor to the class, with the given parameters.
        /// </summary>
        /// <param name="parameterTypes">The types of the parameters of the method.</param>
        /// <returns>The defined constructor.</returns>
        public ConstructorBuilderHelper DefinePublicConstructor(params Type[] parameterTypes)
        {
            return new ConstructorBuilderHelper(
                this,
                _typeBuilder.DefineConstructor(
                    MethodAttributes.Public, CallingConventions.Standard, parameterTypes));
        }

        /// <summary>
        /// Adds a new constructor to the class, with the given attributes and parameters.
        /// </summary>
        /// <param name="attributes">The attributes of the field.</param>
        /// <param name="callingConvention">The <see cref="CallingConventions">calling convention</see> of the method.</param>
        /// <param name="parameterTypes">The types of the parameters of the method.</param>
        /// <returns>The defined constructor.</returns>
        public ConstructorBuilderHelper DefineConstructor(
            MethodAttributes   attributes,
            CallingConventions callingConvention,
            params Type[]      parameterTypes)
        {
            return new ConstructorBuilderHelper(
                this,
                _typeBuilder.DefineConstructor(attributes, callingConvention, parameterTypes));
        }

        #endregion

        #region DefineNestedType Overrides

        /// <summary>
        /// Defines a nested type given its name..
        /// </summary>
        /// <param name="name">The short name of the type.</param>
        /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
        /// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string)">
        /// TypeBuilder.DefineNestedType Method</seealso>
        public TypeBuilderHelper DefineNestedType(string name)
        {
            return new TypeBuilderHelper(_assembly, _typeBuilder.DefineNestedType(name));
        }

        /// <summary>
        /// Defines a public nested type given its name and the type that it extends.
        /// </summary>
        /// <param name="name">The short name of the type.</param>
        /// <param name="parent">The type that the nested type extends.</param>
        /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
        /// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string,TypeAttributes,Type)">
        /// TypeBuilder.DefineNestedType Method</seealso>
        public TypeBuilderHelper DefineNestedType(string name, Type parent)
        {
            return new TypeBuilderHelper(
                _assembly,
                _typeBuilder.DefineNestedType(name, TypeAttributes.NestedPublic, parent));
        }

        /// <summary>
        /// Defines a nested type given its name, attributes, and the type that it extends.
        /// </summary>
        /// <param name="name">The short name of the type.</param>
        /// <param name="attributes">The attributes of the type.</param>
        /// <param name="parent">The type that the nested type extends.</param>
        /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
        /// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string,TypeAttributes,Type)">
        /// TypeBuilder.DefineNestedType Method</seealso>
        public TypeBuilderHelper DefineNestedType(
            string         name,
            TypeAttributes attributes,
            Type           parent)
        {
            return new TypeBuilderHelper(
                _assembly,
                _typeBuilder.DefineNestedType(name, attributes, parent));
        }

        /// <summary>
        /// Defines a public nested type given its name, the type that it extends, and the interfaces that it implements.
        /// </summary>
        /// <param name="name">The short name of the type.</param>
        /// <param name="parent">The type that the nested type extends.</param>
        /// <param name="interfaces">The interfaces that the nested type implements.</param>
        /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
        /// <seealso cref="System.Reflection.Emit.TypeBuilder.DefineNestedType(string,TypeAttributes,Type,Type[])">
        /// TypeBuilder.DefineNestedType Method</seealso>
        public TypeBuilderHelper DefineNestedType(
            string        name,
            Type          parent,
            params Type[] interfaces)
        {
            return new TypeBuilderHelper(
                _assembly,
                _typeBuilder.DefineNestedType(name, TypeAttributes.NestedPublic, parent, interfaces));
        }

        /// <summary>
        /// Defines a nested type given its name, attributes, the type that it extends, and the interfaces that it implements.
        /// </summary>
        /// <param name="name">The short name of the type.</param>
        /// <param name="attributes">The attributes of the type.</param>
        /// <param name="parent">The type that the nested type extends.</param>
        /// <param name="interfaces">The interfaces that the nested type implements.</param>
        /// <returns>Returns the created <see cref="TypeBuilderHelper"/>.</returns>
        /// <seealso cref="System.Reflection.Emit.ModuleBuilder.DefineType(string,TypeAttributes,Type,Type[])">ModuleBuilder.DefineType Method</seealso>
        public TypeBuilderHelper DefineNestedType(
            string         name,
            TypeAttributes attributes,
            Type           parent,
            params         Type[] interfaces)
        {
            return new TypeBuilderHelper(
                _assembly,
                _typeBuilder.DefineNestedType(name, attributes, parent, interfaces));
        }

        #endregion

    }
}
 
© 2010 www.bltoolkit.net
support@bltoolkit.net