Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / ObjectLayer / MetadataAssemblyHelper.cs
1 //---------------------------------------------------------------------
2 // <copyright file="MetadataAssemblyHelper.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 using System.Reflection;
11 using System.Collections.Generic;
12 using System.Diagnostics;
13 using System.Data.Common.Utils;
14
15 namespace System.Data.Metadata.Edm
16 {
17     internal static class MetadataAssemblyHelper
18     {
19         static byte [] EcmaPublicKeyToken = System.Data.EntityModel.SchemaObjectModel.ScalarType.ConvertToByteArray(AssemblyRef.EcmaPublicKey);
20         static byte [] MsPublicKeyToken = System.Data.EntityModel.SchemaObjectModel.ScalarType.ConvertToByteArray(AssemblyRef.MicrosoftPublicKey);
21         private static Memoizer<Assembly, bool> _filterAssemblyCacheByAssembly = new Memoizer<Assembly, bool>(MetadataAssemblyHelper.ComputeShouldFilterAssembly, EqualityComparer<Assembly>.Default);
22
23         internal static Assembly SafeLoadReferencedAssembly(AssemblyName assemblyName)
24         {
25             Assembly assembly = null;
26
27             try
28             {
29                 assembly = Assembly.Load(assemblyName);
30             }
31             catch (System.IO.FileNotFoundException)
32             {
33                 // See 552932: ObjectItemCollection: fails on referenced assemblies that are not available
34             }
35
36             return assembly;
37         }
38
39         private static bool ComputeShouldFilterAssembly(Assembly assembly)
40         {
41             AssemblyName assemblyName = new AssemblyName(assembly.FullName);
42             return ShouldFilterAssembly(assemblyName);
43         }
44         
45         internal static bool ShouldFilterAssembly(Assembly assembly)
46         {
47             return _filterAssemblyCacheByAssembly.Evaluate(assembly);
48         }
49
50         /// <summary>Is the assembly and its referened assemblies not expected to have any metadata</summary>
51         private static bool ShouldFilterAssembly(AssemblyName assemblyName)
52         {
53             return (ArePublicKeyTokensEqual(assemblyName.GetPublicKeyToken(), EcmaPublicKeyToken) ||
54                     ArePublicKeyTokensEqual(assemblyName.GetPublicKeyToken(), MsPublicKeyToken));
55         }
56
57         private static bool ArePublicKeyTokensEqual(byte [] left, byte [] right)
58         {
59             // some assemblies don't have public keys
60             if (left.Length != right.Length)
61             {
62                 return false;
63             }
64
65             for (int i = 0; i < left.Length; i++)
66             {
67                 if (left[i] != right[i])
68                 {
69                     return false;
70                 }
71             }
72             return true;
73         }
74
75         internal static IEnumerable<Assembly> GetNonSystemReferencedAssemblies(Assembly assembly)
76         {
77             foreach (AssemblyName name in assembly.GetReferencedAssemblies())
78             {
79                 if (!ShouldFilterAssembly(name))
80                 {
81                     Assembly referenceAssembly = SafeLoadReferencedAssembly(name);
82                     if(referenceAssembly != null )
83                     {
84                         yield return referenceAssembly;
85                     }
86                 }
87             }
88         }
89      }
90 }