MiniAssembly.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / AddIn / AddIn / System / Addin / MiniReflection / MiniAssembly.cs / 1305376 / MiniAssembly.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*============================================================
** 
** Class:  MiniAssembly 
**
** Purpose: Wraps an assembly, using a managed PE reader to 
**     interpret the metadata.
**
===========================================================*/
using System; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Globalization; 
using System.IO;
using System.Text; 
using System.AddIn.MiniReflection.MetadataReader;
using System.Diagnostics;
using System.AddIn.Hosting;
using System.Diagnostics.Contracts; 

namespace System.AddIn.MiniReflection 
{ 
    [Serializable]
    internal sealed class MiniAssembly : MiniModule 
    {
        private enum Representation {
            PEFileReader = 1,
            ReflectionAssembly = 2, 
        }
 
        // When loading other assemblies, which directory should we look in? 
        private List _dependencyDirs;
        private Representation _representation; 
        private System.Reflection.Assembly _reflectionAssembly;
        private String _fullName;

        public MiniAssembly(String peFileName) : base(peFileName) 
        {
            _dependencyDirs = new List(); 
            _dependencyDirs.Add(Path.GetDirectoryName(peFileName)); 
            Assembly = this;
            _representation = Representation.PEFileReader; 
        }

        public MiniAssembly(System.Reflection.Assembly assembly)
        { 
            System.Diagnostics.Contracts.Contract.Requires(assembly != null);
 
            _reflectionAssembly = assembly; 
            _representation = Representation.ReflectionAssembly;
        } 

        public List DependencyDirs
        {
            get { return _dependencyDirs; } 
        }
 
        internal bool IsReflectionAssembly { 
            get { return (_representation & Representation.ReflectionAssembly) != 0; }
        } 

        public MiniModule[] GetModules()
        {
            // There are two forms of "multiple module" assemblies.  The first is a 
            // multi-module assembly where the assembly's ModuleRef lists multiple
            // different modules.  The second is a multi-file assembly, where an 
            // entry in the File metadata table refers to another file on disk and 
            // explicitly declares the file contains metadata (and potentially types).
            // ALink can produce .netmodules, which seem to show up as multi-file 
            // assemblies.
            MDTables metaData = _peFile.MetaData;

            for(uint i=0; i GetTypesWithAttribute(Type customAttribute) 
        {
            return GetTypesWithAttribute(customAttribute, false);
        }
 
        public TypeInfo FindTypeInfo(String typeName, String nameSpace)
        { 
            System.Diagnostics.Contracts.Contract.Assert(!IsReflectionAssembly); // Can be implemented using Assembly.GetType 
            MetadataToken token = FindTypeDef(_peFile, _peFile.MetaData, typeName, nameSpace);
            return new TypeInfo(token, this, typeName, nameSpace); 
        }

        private static MetadataToken FindTypeDef(PEFileReader peFile, MDTables mdScope, String typeName, String nameSpace)
        { 
            System.Diagnostics.Contracts.Contract.Requires(typeName != null);
 
            uint numTypeDefs = mdScope.RowsInTable(MDTables.Tables.TypeDef); 
            for (uint i = 0; i < numTypeDefs; i++) {
                mdScope.SeekToRowOfTable(MDTables.Tables.TypeDef, i); 
                peFile.B.ReadUInt32();  // TypeAttributes
                String rowTypeName = mdScope.ReadString();
                if (!String.Equals(typeName, rowTypeName))
                    continue; 
                String rowNameSpace= mdScope.ReadString();
                if (!String.Equals(nameSpace, rowNameSpace)) 
                    continue; 
                return new MetadataToken(MDTables.Tables.TypeDef, i + 1);
            } 
            throw new TypeLoadException(String.Format(CultureInfo.CurrentCulture, Res.CantFindTypeName, nameSpace, typeName));
        }

        // For each module in the assembly, give back all types with the 
        // given attribute, possibly respecting the type's visibility.
        public IList GetTypesWithAttribute(Type customAttribute, bool includePrivate) 
        { 
            if (IsDisposed)
                throw new ObjectDisposedException(null); 
            if (customAttribute == null)
                throw new ArgumentNullException("customAttribute");
            System.Diagnostics.Contracts.Contract.EndContractBlock();
 
            List types = new List();
            foreach (MiniModule module in GetModules()) 
            { 
                IList newTypes = module.GetTypesWithAttributeInModule(customAttribute, includePrivate);
                types.AddRange(newTypes); 
            }
            return types;
        }
 
        public MiniAssembly ResolveAssemblyRef(MetadataToken token, bool throwOnError)
        { 
            System.Diagnostics.Contracts.Contract.Requires(token.Table == MDTables.Tables.AssemblyRef); 
            PEFileReader peFile = this.PEFileReader;
            MDTables metaData = peFile.MetaData; 

            metaData.SeekToMDToken(token);
            peFile.B.ReadUInt64();  // Skip 4 parts of the version number.
            peFile.B.ReadUInt32();  // AssemblyFlags 
            byte[] publicKeyOrToken = metaData.ReadBlob(); // Public key or token
            String assemblySimpleName = metaData.ReadString(); // simple name 
            String cultureName = metaData.ReadString();  // assembly culture 
            if (!String.IsNullOrEmpty(cultureName))
                throw new BadImageFormatException(Res.UnexpectedlyLoadingASatellite, FullName); 

            if (assemblySimpleName == "mscorlib" && (cultureName.Length == 0 || cultureName == "neutral"))
                return new MiniAssembly(typeof(Object).Assembly);
 
            MiniAssembly loadedAssembly = Open(assemblySimpleName, _dependencyDirs, throwOnError);
 
            if (loadedAssembly != null) 
            {
                // Check whether the reference to the assembly matches what we actually loaded. 
                // We don't respect the "throwOnError" parameter here because if someone does
                // violate this, they've either severely messed up their deployment, or they're
                // attempting a security exploit.
                System.Reflection.AssemblyName loadedAssemblyName = 
                    new System.Reflection.AssemblyName(loadedAssembly.FullName);
 
                if (!Utils.PublicKeyMatches(loadedAssemblyName, publicKeyOrToken)) 
                {
                    throw new FileLoadException(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadRefDefMismatch, 
                        assemblySimpleName, publicKeyOrToken, loadedAssemblyName.GetPublicKeyToken()));
                }

                if (!String.IsNullOrEmpty(loadedAssemblyName.CultureInfo.Name)) 
                {
                    throw new FileLoadException(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadRefDefMismatch, 
                        assemblySimpleName, String.Empty, loadedAssemblyName.CultureInfo.Name)); 
                }
            } 
            return loadedAssembly;
        }

        public static MiniAssembly Open(String simpleName, IList dependencyDirs, bool throwOnError) 
        {
            String fileName = FindAssembly(simpleName, dependencyDirs, throwOnError); 
            if (!throwOnError && fileName == null) 
                return null;
            return new MiniAssembly(fileName); 
        }

        private static String FindAssembly(String simpleName, IList searchDirs, bool throwOnError)
        { 
            System.Diagnostics.Contracts.Contract.Requires(!String.IsNullOrEmpty(simpleName));
            System.Diagnostics.Contracts.Contract.Requires(searchDirs != null); 
 
            String libName = simpleName + ".dll";
            String exeName = simpleName + ".exe"; 
            foreach (String dir in searchDirs)
            {
                String fileName = Path.Combine(dir, libName);
                if (File.Exists(fileName)) 
                    return fileName;
 
                fileName = Path.Combine(dir, exeName); 
                if (File.Exists(fileName))
                    return fileName; 
            }
            if (throwOnError)
                throw new FileNotFoundException(String.Format(CultureInfo.CurrentCulture, Res.FileNotFoundForInspection, simpleName), libName);
            else 
                return null;
        } 
 
        internal String FullName {
            get { 
                if ((_representation & Representation.ReflectionAssembly) != 0)
                    return AppDomain.CurrentDomain.ApplyPolicy(_reflectionAssembly.FullName);

                if (_fullName == null) { 
                    AssemblyInfo assemblyInfo = new AssemblyInfo();
                    _peFile.GetAssemblyInfo(ref assemblyInfo); 
                    _fullName = AppDomain.CurrentDomain.ApplyPolicy(assemblyInfo.ToString()); 
                }
 
                return _fullName;
            }
        }
 
        public override bool Equals(object obj)
        { 
            MiniAssembly thatAssembly = obj as MiniAssembly; 
            if (thatAssembly == null)
                return false; 
            // Note that assembly binding redirects and publisher policy will affect
            // versioning (ie binds to 2.0.0.0 redirected to 2.0.1.5).  But for
            // the Orcas release, we're only planning on using our existing
            // directory structure, which does not have a great servicing story. 
            // As long as we use ReflectionOnlyLoad during discovery, we should
            // be fetching the exact assembly on disk used to build the entire 
            // pipeline (modulo in-place updates which must keep the same 
            // assembly version number), and we'll load the right version
            // during activation time.  That should work for Orcas. 
            // Long term, we may need an approximately-equals method that gets
            // the assembly info and compares the version number w.r.t. policy.
            return Utils.AssemblyDefEqualsDef(FullName, thatAssembly.FullName);
        } 

        // See the comments in Equals - we're doing string comparisons here 
        // to compare full type names. 
        public static bool Equals(MiniAssembly assemblyA, PEFileReader peFileB, MetadataToken assemblyRefB)
        { 
            System.Diagnostics.Contracts.Contract.Requires(assemblyA != null);
            System.Diagnostics.Contracts.Contract.Requires(peFileB != null);
            System.Diagnostics.Contracts.Contract.Requires(assemblyRefB.Table == MDTables.Tables.AssemblyRef);
 
            String nameA, nameRefB;
            if (assemblyA.IsReflectionAssembly) 
                nameA = AppDomain.CurrentDomain.ApplyPolicy(assemblyA._reflectionAssembly.FullName); 
            else
            { 
                AssemblyInfo assemblyInfoA = new AssemblyInfo();
                assemblyA._peFile.GetAssemblyInfo(ref assemblyInfoA);
                nameA = AppDomain.CurrentDomain.ApplyPolicy(assemblyInfoA.ToString());
            } 

            AssemblyInfo assemblyInfoB = ReadAssemblyRef(peFileB, assemblyRefB); 
            nameRefB = AppDomain.CurrentDomain.ApplyPolicy(assemblyInfoB.ToString()); 

            return Utils.AssemblyRefEqualsDef(nameRefB, nameA); 
        }

        private static AssemblyInfo ReadAssemblyRef(PEFileReader peFile, MetadataToken assemblyRef)
        { 
            System.Diagnostics.Contracts.Contract.Requires(peFile != null);
            System.Diagnostics.Contracts.Contract.Requires(assemblyRef.Table == MDTables.Tables.AssemblyRef); 
            MDTables metaData = peFile.MetaData; 
            BinaryReader B = metaData.B;
 
            metaData.SeekToMDToken(assemblyRef);
            UInt16 major = B.ReadUInt16();
            UInt16 minor = B.ReadUInt16();
            UInt16 build = B.ReadUInt16(); 
            UInt16 revision = B.ReadUInt16();
            Version v = new Version(major, minor, build, revision); 
            UInt32 assemblyFlags = B.ReadUInt32(); 
            byte[] publicKey = metaData.ReadBlob();
            String simpleName = metaData.ReadString(); 
            String culture = metaData.ReadString();
            if ((culture != null) && (culture.Length == 0)) culture = null;
            return new AssemblyInfo(v, assemblyFlags, publicKey, simpleName, culture);
        } 

        public override int GetHashCode() 
        { 
            return FullName.GetHashCode();
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK