This repository has been archived by the owner on Nov 25, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 104
/
WebHostHttpControllerTypeResolver.cs
91 lines (81 loc) · 3.76 KB
/
WebHostHttpControllerTypeResolver.cs
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
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. 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.Web.Compilation;
using System.Web.Http.Dispatcher;
namespace System.Web.Http.WebHost
{
/// <summary>
/// Wraps ASP build manager
/// </summary>
internal sealed class WebHostHttpControllerTypeResolver : DefaultHttpControllerTypeResolver
{
private const string TypeCacheName = "MS-ApiControllerTypeCache.xml";
/// <summary>
/// Returns a list of controllers available for the application.
/// </summary>
/// <returns>An <see cref="ICollection{Type}" /> of controllers.</returns>
public override ICollection<Type> GetControllerTypes(IAssembliesResolver assembliesResolver)
{
HttpControllerTypeCacheSerializer serializer = new HttpControllerTypeCacheSerializer();
// First, try reading from the cache on disk
List<Type> matchingTypes = ReadTypesFromCache(TypeCacheName, IsControllerTypePredicate, serializer);
if (matchingTypes != null)
{
return matchingTypes;
}
// If reading from the cache failed, enumerate over every assembly looking for a matching type
matchingTypes = base.GetControllerTypes(assembliesResolver).ToList();
// Finally, save the cache back to disk
SaveTypesToCache(TypeCacheName, matchingTypes, serializer);
return matchingTypes;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Cache failures are not fatal, and the code should continue executing normally.")]
private static List<Type> ReadTypesFromCache(string cacheName, Predicate<Type> predicate, HttpControllerTypeCacheSerializer serializer)
{
try
{
Stream stream = BuildManager.ReadCachedFile(cacheName);
if (stream != null)
{
using (StreamReader reader = new StreamReader(stream))
{
ICollection<Type> deserializedTypes = serializer.DeserializeTypes(reader);
if (deserializedTypes != null && deserializedTypes.All(type => predicate(type)))
{
// If all read types still match the predicate, success!
return deserializedTypes.ToList();
}
}
}
}
catch
{
// cache failures are not considered fatal -- keep running.
}
return null;
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "Cache failures are not fatal, and the code should continue executing normally.")]
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Disposed later")]
private static void SaveTypesToCache(string cacheName, IEnumerable<Type> matchingTypes, HttpControllerTypeCacheSerializer serializer)
{
try
{
Stream stream = BuildManager.CreateCachedFile(cacheName);
if (stream != null)
{
using (StreamWriter writer = new StreamWriter(stream))
{
serializer.SerializeTypes(matchingTypes, writer);
}
}
}
catch
{
// cache failures are not considered fatal -- keep running.
}
}
}
}