File: DefaultAssemblyResolver.cs

package info (click to toggle)
mono 6.14.1%2Bds2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,282,732 kB
  • sloc: cs: 11,182,461; xml: 2,850,281; ansic: 699,123; cpp: 122,919; perl: 58,604; javascript: 30,841; asm: 21,845; makefile: 19,602; sh: 10,973; python: 4,772; pascal: 925; sql: 859; sed: 16; php: 1
file content (184 lines) | stat: -rw-r--r-- 6,801 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
//---------------------------------------------------------------------
// <copyright file="DefaultAssemblyResolver.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------

using System.Reflection;
using System.IO;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Collections;

namespace System.Data.Metadata.Edm
{
    internal class DefaultAssemblyResolver : MetadataArtifactAssemblyResolver
    {
        internal override bool TryResolveAssemblyReference(AssemblyName refernceName, out Assembly assembly)
        {
            assembly = ResolveAssembly(refernceName);
            return assembly != null;
        }


        internal override IEnumerable<Assembly> GetWildcardAssemblies()
        {
            return GetAllDiscoverableAssemblies();
        }

        internal Assembly ResolveAssembly(AssemblyName referenceName)
        {
            Assembly assembly = null;

            // look in the already loaded assemblies
            foreach (Assembly current in GetAlreadyLoadedNonSystemAssemblies())
            {
                if (AssemblyName.ReferenceMatchesDefinition(referenceName, new AssemblyName(current.FullName)))
                {
                    return current;
                }
            }

            // try to load this one specifically
            if (assembly == null)
            {
                assembly = MetadataAssemblyHelper.SafeLoadReferencedAssembly(referenceName);
                if (assembly != null)
                {
                    return assembly;
                }
            }

            // try all the discoverable ones
            TryFindWildcardAssemblyMatch(referenceName, out assembly);

            return assembly;
        }

        private bool TryFindWildcardAssemblyMatch(AssemblyName referenceName, out Assembly assembly)
        {
            Debug.Assert(referenceName != null);

            foreach (Assembly current in GetAllDiscoverableAssemblies())
            {
                if (AssemblyName.ReferenceMatchesDefinition(referenceName, new AssemblyName(current.FullName)))
                {
                    assembly = current;
                    return true;
                }
            }

            assembly = null;
            return false;
        }


        /// <summary>
        /// Return all assemblies loaded in the current AppDomain that are not signed
        /// with the Microsoft Key.
        /// </summary>
        /// <returns>A list of assemblies</returns>
        private static IEnumerable<Assembly> GetAlreadyLoadedNonSystemAssemblies()
        {
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            return assemblies.Where(a => a != null && !MetadataAssemblyHelper.ShouldFilterAssembly(a));
        }

        /// <summary>
        /// This method returns a list of assemblies whose contents depend on whether we
        /// are running in an ASP.NET environment. If we are indeed in a Web/ASP.NET
        /// scenario, we pick up the assemblies that all page compilations need to
        /// reference. If not, then we simply get the list of assemblies referenced by
        /// the entry assembly.
        /// </summary>
        /// <returns>A list of assemblies</returns>
        private static IEnumerable<Assembly> GetAllDiscoverableAssemblies()
        {
            Assembly assembly = Assembly.GetEntryAssembly();
            HashSet<Assembly> assemblyList = new HashSet<Assembly>(
                AssemblyComparer.Instance);

            foreach (Assembly loadedAssembly in GetAlreadyLoadedNonSystemAssemblies())
            {
                assemblyList.Add(loadedAssembly);
            }

            AspProxy aspProxy = new AspProxy();
            if (!aspProxy.IsAspNetEnvironment())
            {
                if (assembly == null)
                {
                    return assemblyList;
                }

                assemblyList.Add(assembly);

                foreach (Assembly referenceAssembly in MetadataAssemblyHelper.GetNonSystemReferencedAssemblies(assembly))
                {
                    assemblyList.Add(referenceAssembly);
                }

                return assemblyList;
            }

            if (aspProxy.HasBuildManagerType())
            {
                IEnumerable<Assembly> referencedAssemblies = aspProxy.GetBuildManagerReferencedAssemblies();
                // filter out system assemblies
                if (referencedAssemblies != null)
                {
                    foreach (Assembly referencedAssembly in referencedAssemblies)
                    {
                        if (MetadataAssemblyHelper.ShouldFilterAssembly(referencedAssembly))
                        {
                            continue;
                        }

                        assemblyList.Add(referencedAssembly);
                    }
                }
            }

            return assemblyList.Where(a => a != null);
        }

        internal sealed class AssemblyComparer : IEqualityComparer<Assembly>
        {
            // use singleton
            private AssemblyComparer() { }

            private static AssemblyComparer _instance = new AssemblyComparer();
            public static AssemblyComparer Instance{ get { return _instance; } }

            /// <summary>
            /// if two assemblies have the same full name, we will consider them as the same.
            /// for example,
            /// both of x and y have the full name as "{RES, Version=3.5.0.0, Culture=neutral, PublicKeyToken=null}",
            /// although they are different instances since the ReflectionOnly field in them are different, we sitll 
            /// consider them as the same.
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public bool Equals(Assembly x, Assembly y)
            {
                AssemblyName xname = new AssemblyName(x.FullName);
                AssemblyName yname = new AssemblyName(y.FullName);
                // return *true* when either the reference are the same 
                // *or* the Assembly names are commutative equal
                return object.ReferenceEquals(x, y)
                    || (AssemblyName.ReferenceMatchesDefinition(xname, yname)
                         && AssemblyName.ReferenceMatchesDefinition(yname, xname));
            }

            public int GetHashCode(Assembly assembly)
            {
                return assembly.FullName.GetHashCode();
            }
        }
    }
}