forked from aspnet/AspNetWebStack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRemoteAssembly.cs
More file actions
201 lines (173 loc) · 6.86 KB
/
Copy pathRemoteAssembly.cs
File metadata and controls
201 lines (173 loc) · 6.86 KB
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Web.WebPages.Deployment;
using NuGet.Runtime;
namespace System.Web.WebPages.Administration.PackageManager
{
// We need to make changes to NuGet.Core once we ship Beta so that this type is removed.
internal class RemoteAssembly : MarshalByRefObject, IAssembly, IEquatable<RemoteAssembly>, IComparable<RemoteAssembly>
{
private readonly List<IAssembly> _referencedAssemblies = new List<IAssembly>();
internal RemoteAssembly()
{
}
internal RemoteAssembly(string name, Version version, string publicKeyToken, string culture)
{
Name = name;
Version = version;
PublicKeyToken = publicKeyToken;
Culture = culture;
}
public string Name { get; private set; }
public Version Version { get; private set; }
public string PublicKeyToken { get; private set; }
public string Culture { get; private set; }
public IEnumerable<IAssembly> ReferencedAssemblies
{
get { return _referencedAssemblies; }
}
public void Load(string assemblyString, bool isPath)
{
Assembly assembly;
if (isPath)
{
assembly = Assembly.ReflectionOnlyLoadFrom(assemblyString);
}
else
{
assembly = Assembly.ReflectionOnlyLoad(assemblyString);
}
// Get the assembly name and set the properties on this object
CopyAssemblyProperties(assembly.GetName(), this);
// Do the same for referenced assemblies
foreach (AssemblyName referencedAssemblyName in assembly.GetReferencedAssemblies())
{
// Copy the properties to the referenced assembly
var referencedAssembly = new RemoteAssembly();
_referencedAssemblies.Add(CopyAssemblyProperties(referencedAssemblyName, referencedAssembly));
}
}
private static RemoteAssembly CopyAssemblyProperties(AssemblyName assemblyName, RemoteAssembly assembly)
{
assembly.Name = assemblyName.Name;
assembly.Version = assemblyName.Version;
assembly.PublicKeyToken = assemblyName.GetPublicKeyTokenString();
string culture = assemblyName.CultureInfo.ToString();
if (String.IsNullOrEmpty(culture))
{
assembly.Culture = "neutral";
}
else
{
assembly.Culture = culture;
}
return assembly;
}
internal static IAssembly LoadAssembly(string assemblyString, AppDomain domain, bool isPath)
{
if (domain != AppDomain.CurrentDomain)
{
var crossDomainAssembly = domain.CreateInstance<RemoteAssembly>();
crossDomainAssembly.Load(assemblyString, isPath);
return crossDomainAssembly;
}
var assembly = new RemoteAssembly();
assembly.Load(assemblyString, isPath);
return assembly;
}
public static IEnumerable<IAssembly> GetAssembliesForBindingRedirect(AppDomain appDomain, string binDirectoryPath)
{
return GetAssembliesForBindingRedirect(appDomain, binDirectoryPath, GetBinAssemblies);
}
internal static IEnumerable<IAssembly> GetAssembliesForBindingRedirect(AppDomain appDomain, string binDirectoryPath, Func<AppDomain, string, IEnumerable<IAssembly>> getBinAssemblies)
{
var binAssemblies = getBinAssemblies(appDomain, binDirectoryPath).ToList();
if (!binAssemblies.Any())
{
return binAssemblies;
}
var webPagesAssemblies = from asm in WebPagesDeployment.GetWebPagesAssemblies()
select LoadAssembly(asm.FullName, appDomain, isPath: false);
return webPagesAssemblies.Concat(binAssemblies)
.Distinct()
.ToList();
}
private static IEnumerable<IAssembly> GetBinAssemblies(AppDomain appDomain, string binDirectoryPath)
{
if (!Directory.Exists(binDirectoryPath))
{
yield break;
}
var extensions = new[] { "*.dll", "*.exe" };
foreach (var extension in extensions)
{
foreach (var path in Directory.EnumerateFiles(binDirectoryPath, extension))
{
IAssembly assembly = LoadAssemblyFromSafe(appDomain, path);
if (assembly != null)
{
yield return assembly;
}
}
}
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We're loading arbitrary binaries from the bin and some of them might not be native. Catch all to prevent this from throwing.")]
private static IAssembly LoadAssemblyFromSafe(AppDomain appDomain, string path)
{
try
{
return LoadAssembly(path, appDomain, isPath: true);
}
catch
{
// We don't want to throw from this method.
}
return null;
}
public override bool Equals(object obj)
{
var otherAssembly = obj as RemoteAssembly;
return otherAssembly != null && Equals(otherAssembly);
}
public bool Equals(RemoteAssembly other)
{
return CompareTo(other) == 0;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
public int CompareTo(RemoteAssembly other)
{
return Compare(this, other);
}
internal static int Compare(IAssembly a, IAssembly b)
{
if (b == null)
{
return 1;
}
var nameDiff = StringComparer.OrdinalIgnoreCase.Compare(a.Name, b.Name);
if (nameDiff != 0)
{
return nameDiff;
}
var versionDiff = a.Version.CompareTo(b.Version);
if (versionDiff != 0)
{
return versionDiff;
}
var publicKeyDiff = StringComparer.OrdinalIgnoreCase.Compare(a.PublicKeyToken, b.PublicKeyToken);
if (publicKeyDiff != 0)
{
return publicKeyDiff;
}
return StringComparer.OrdinalIgnoreCase.Compare(a.Culture, b.Culture);
}
}
}