Click here to Skip to main content
15,884,425 members
Articles / Programming Languages / C#

Accessing Assembly Metadata with Reflection or Mono Cecil (Part 6)

Rate me:
Please Sign up or sign in to vote.
5.00/5 (7 votes)
2 Dec 2012CDDL16 min read 42.2K   936   20  
Loading type metadata from assemblies with Reflection or Mono Cecil.
// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using Nova.Parsing;
using Nova.Rendering;

namespace Nova.CodeDOM
{
    /// <summary>
    /// Represents a user-defined conversion operator.
    /// </summary>
    /// <remarks>
    /// Conversion operators must have either the implicit or explicit modifier, a single parameter,
    /// and either the parameter type OR the destination type (return type) must be the containing type.
    /// They can only be defined by class or struct types, and must be public and static.
    /// </remarks>
    public class ConversionOperatorDecl : OperatorDecl
    {
        #region /* CONSTRUCTORS */

        /// <summary>
        /// Create a <see cref="ConversionOperatorDecl"/>.
        /// </summary>
        public ConversionOperatorDecl(Expression destinationType, Modifiers modifiers, CodeObject body, ParameterDecl parameter)
            : base(GetInternalName(modifiers), destinationType, modifiers, body, new[] { parameter })
        { }

        /// <summary>
        /// Create a <see cref="ConversionOperatorDecl"/>.
        /// </summary>
        public ConversionOperatorDecl(Expression destinationType, Modifiers modifiers, ParameterDecl parameter)
            : base(GetInternalName(modifiers), destinationType, modifiers, new[] { parameter })
        { }

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// True if the conversion is explicit.
        /// </summary>
        public bool IsExplicit
        {
            get { return _modifiers.HasFlag(Modifiers.Explicit); }
        }

        /// <summary>
        /// True if the conversion is implicit.
        /// </summary>
        public bool IsImplicit
        {
            get { return _modifiers.HasFlag(Modifiers.Implicit); }
        }

        #endregion

        #region /* METHODS */

        private static string GetInternalName(Modifiers modifiers)
        {
            string name = Operator.NamePrefix;
            if (modifiers.HasFlag(Modifiers.Implicit))
                name += Modifiers.Implicit.ToString();
            else if (modifiers.HasFlag(Modifiers.Explicit))
                name += Modifiers.Explicit.ToString();
            return name;
        }

        /// <summary>
        /// Get the full name of the <see cref="INamedCodeObject"/>, including any namespace name.
        /// </summary>
        /// <param name="descriptive">True to display type parameters and method parameters, otherwise false.</param>
        public override string GetFullName(bool descriptive)
        {
            string name = (IsExplicit ? "explicit" : (IsImplicit ? "implicit" : "")) + " " + ParseToken + " " + _returnType.GetDescription();
            if (descriptive)
                name += GetParametersAsString();
            if (_parent is TypeDecl)
                name = ((TypeDecl)_parent).GetFullName(descriptive) + "." + name;
            return name;
        }

        #endregion

        #region /* PARSING */

        /// <summary>
        /// Parse a <see cref="ConversionOperatorDecl"/>.
        /// </summary>
        public ConversionOperatorDecl(Parser parser, CodeObject parent, ParseFlags flags)
            : base(parser, parent, false, flags)
        {
            parser.NextToken();                                 // Move past 'operator'
            _modifiers = ModifiersHelpers.Parse(parser, this);  // Parse any modifiers in reverse from the Unused list
            _name = GetInternalName(_modifiers);                // Get the name
            ParseUnusedAnnotations(parser, this, false);        // Parse attributes and/or doc comments from the Unused list
            SetField(ref _returnType, Expression.Parse(parser, this, true, Expression.ParseTokenStartGroup), false);
            ParseParameters(parser);
            ParseTerminatorOrBody(parser, flags);
        }

        #endregion

        #region /* RENDERING */

        internal override void AsTextName(CodeWriter writer, RenderFlags flags)
        {
            RenderFlags passFlags = (flags & RenderFlags.PassMask);
            _returnType.AsText(writer, passFlags);
        }

        protected override void AsTextStatement(CodeWriter writer, RenderFlags flags)
        {
            UpdateLineCol(writer, flags);
            writer.Write(ParseToken + " ");
            if (flags.HasFlag(RenderFlags.Description) && _parent is TypeDecl)
            {
                ((TypeDecl)_parent).AsTextName(writer, flags);
                writer.Write(Dot.ParseToken);
            }
            AsTextName(writer, flags);
        }

        #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 Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions