/
DynamicApis.cs
238 lines (202 loc) · 11.6 KB
/
DynamicApis.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
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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
//-----------------------------------------------------------------------
// <copyright file="DynamicApis.cs" company="NSwag">
// Copyright (c) Rico Suter. All rights reserved.
// </copyright>
// <license>https://github.com/NSwag/NSwag/blob/master/LICENSE.md</license>
// <author>Rico Suter, mail@rsuter.com</author>
//-----------------------------------------------------------------------
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace NJsonSchema.Infrastructure
{
/// <summary>Provides dynamic access to framework APIs.</summary>
public static class DynamicApis
{
private static readonly Type XPathExtensionsType;
private static readonly Type FileType;
private static readonly Type DirectoryType;
private static readonly Type PathType;
private static readonly Type HttpClientType;
static DynamicApis()
{
XPathExtensionsType = TryLoadType(
"System.Xml.XPath.Extensions, System.Xml.XPath.XDocument",
"System.Xml.XPath.Extensions, System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
HttpClientType = TryLoadType(
"System.Net.Http.HttpClient, System.Net.Http",
"System.Net.Http.HttpClient, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
FileType = TryLoadType("System.IO.File, System.IO.FileSystem", "System.IO.File");
DirectoryType = TryLoadType("System.IO.Directory, System.IO.FileSystem", "System.IO.Directory");
PathType = TryLoadType("System.IO.Path, System.IO.FileSystem", "System.IO.Path");
}
/// <summary>Gets a value indicating whether file APIs are available.</summary>
public static bool SupportsFileApis => FileType != null;
/// <summary>Gets a value indicating whether path APIs are available.</summary>
public static bool SupportsPathApis => PathType != null;
/// <summary>Gets a value indicating whether path APIs are available.</summary>
public static bool SupportsDirectoryApis => DirectoryType != null;
/// <summary>Gets a value indicating whether XPath APIs are available.</summary>
public static bool SupportsXPathApis => XPathExtensionsType != null;
/// <summary>Gets a value indicating whether WebClient APIs are available.</summary>
public static bool SupportsHttpClientApis => HttpClientType != null;
/// <summary>Request the given URL via HTTP.</summary>
/// <param name="url">The URL.</param>
/// <returns>The content.</returns>
/// <exception cref="NotSupportedException">The HttpClient.GetAsync API is not available on this platform.</exception>
public static async Task<string> HttpGetAsync(string url)
{
if (!SupportsHttpClientApis)
throw new NotSupportedException("The System.Net.Http.HttpClient API is not available on this platform.");
using (dynamic client = (IDisposable)Activator.CreateInstance(HttpClientType))
{
var response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStringAsync();
}
}
/// <summary>Gets the current working directory.</summary>
/// <returns>The directory path.</returns>
/// <exception cref="NotSupportedException">The System.IO.Directory API is not available on this platform.</exception>
public static Task<string> DirectoryGetCurrentDirectoryAsync()
{
if (!SupportsDirectoryApis)
throw new NotSupportedException("The System.IO.Directory API is not available on this platform.");
return FromResult((string)DirectoryType.GetRuntimeMethod("GetCurrentDirectory", new Type[] { }).Invoke(null, new object[] { }));
}
/// <summary>Gets the files of the given directory.</summary>
/// <param name="directory">The directory.</param>
/// <param name="filter">The filter.</param>
/// <returns>The file paths.</returns>
/// <exception cref="NotSupportedException">The System.IO.Directory API is not available on this platform.</exception>
public static Task<string[]> DirectoryGetFilesAsync(string directory, string filter)
{
if (!SupportsDirectoryApis)
throw new NotSupportedException("The System.IO.Directory API is not available on this platform.");
return FromResult((string[])DirectoryType.GetRuntimeMethod("GetFiles",
new[] { typeof(string), typeof(string) }).Invoke(null, new object[] { directory, filter }));
}
/// <summary>Creates a directory.</summary>
/// <param name="directory">The directory.</param>
/// <exception cref="NotSupportedException">The System.IO.Directory API is not available on this platform.</exception>
public static Task DirectoryCreateDirectoryAsync(string directory)
{
if (!SupportsDirectoryApis)
throw new NotSupportedException("The System.IO.Directory API is not available on this platform.");
return FromResult(DirectoryType.GetRuntimeMethod("CreateDirectory",
new[] { typeof(string) }).Invoke(null, new object[] { directory }));
}
/// <summary>Checks whether a directory exists.</summary>
/// <param name="filePath">The file path.</param>
/// <returns>true or false</returns>
/// <exception cref="NotSupportedException">The System.IO.Directory API is not available on this platform.</exception>
public static async Task<bool> DirectoryExistsAsync(string filePath)
{
if (!SupportsDirectoryApis)
throw new NotSupportedException("The System.IO.Directory API is not available on this platform.");
if (string.IsNullOrEmpty(filePath))
return false;
return await FromResult((bool)DirectoryType.GetRuntimeMethod("Exists",
new[] { typeof(string) }).Invoke(null, new object[] { filePath })).ConfigureAwait(false);
}
/// <summary>Checks whether a file exists.</summary>
/// <param name="filePath">The file path.</param>
/// <returns>true or false</returns>
/// <exception cref="NotSupportedException">The System.IO.File API is not available on this platform.</exception>
public static async Task<bool> FileExistsAsync(string filePath)
{
if (!SupportsFileApis)
throw new NotSupportedException("The System.IO.File API is not available on this platform.");
if (string.IsNullOrEmpty(filePath))
return false;
return await FromResult((bool)FileType.GetRuntimeMethod("Exists",
new[] { typeof(string) }).Invoke(null, new object[] { filePath })).ConfigureAwait(false);
}
/// <summary>Reads all content of a file (UTF8).</summary>
/// <param name="filePath">The file path.</param>
/// <returns>The file content.</returns>
/// <exception cref="NotSupportedException">The System.IO.File API is not available on this platform.</exception>
public static Task<string> FileReadAllTextAsync(string filePath)
{
if (!SupportsFileApis)
throw new NotSupportedException("The System.IO.File API is not available on this platform.");
return Task.Factory.StartNew(() => (string)FileType.GetRuntimeMethod("ReadAllText",
new[] { typeof(string), typeof(Encoding) }).Invoke(null, new object[] { filePath, Encoding.UTF8 }));
}
/// <summary>Writes text to a file (UTF8).</summary>
/// <param name="filePath">The file path.</param>
/// <param name="text">The text.</param>
/// <returns></returns>
/// <exception cref="NotSupportedException">The System.IO.File API is not available on this platform.</exception>
public static Task FileWriteAllTextAsync(string filePath, string text)
{
if (!SupportsFileApis)
throw new NotSupportedException("The System.IO.File API is not available on this platform.");
return FromResult(FileType.GetRuntimeMethod("WriteAllText",
new[] { typeof(string), typeof(string), typeof(Encoding) }).Invoke(null, new object[] { filePath, text, Encoding.UTF8 }));
}
/// <summary>Combines two paths.</summary>
/// <param name="path1">The path1.</param>
/// <param name="path2">The path2.</param>
/// <returns>The combined path.</returns>
/// <exception cref="NotSupportedException">The System.IO.Path API is not available on this platform.</exception>
public static string PathCombine(string path1, string path2)
{
if (!SupportsPathApis)
throw new NotSupportedException("The System.IO.Path API is not available on this platform.");
return (string)PathType.GetRuntimeMethod("Combine", new[] { typeof(string), typeof(string) }).Invoke(null, new object[] { path1, path2 });
}
/// <summary>Gets the directory path of a file path.</summary>
/// <param name="filePath">The file path.</param>
/// <returns>The directory name.</returns>
/// <exception cref="NotSupportedException">The System.IO.Path API is not available on this platform.</exception>
public static string PathGetDirectoryName(string filePath)
{
if (!SupportsPathApis)
throw new NotSupportedException("The System.IO.Path API is not available on this platform.");
return (string)PathType.GetRuntimeMethod("GetDirectoryName", new[] { typeof(string) }).Invoke(null, new object[] { filePath });
}
/// <summary>Evaluates the XPath for a given XML document.</summary>
/// <param name="document">The document.</param>
/// <param name="path">The path.</param>
/// <returns>The value.</returns>
/// <exception cref="NotSupportedException">The System.Xml.XPath.Extensions API is not available on this platform.</exception>
public static object XPathEvaluate(XDocument document, string path)
{
if (!SupportsXPathApis)
throw new NotSupportedException("The System.Xml.XPath.Extensions API is not available on this platform.");
return XPathExtensionsType.GetRuntimeMethod("XPathEvaluate", new[] { typeof(XDocument), typeof(string) }).Invoke(null, new object[] { document, path });
}
#if LEGACY
internal static async Task<T> FromResult<T>(T result)
{
return result;
}
#else
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Task<T> FromResult<T>(T result)
{
return Task.FromResult(result);
}
#endif
private static Type TryLoadType(params string[] typeNames)
{
foreach (var typeName in typeNames)
{
try
{
var type = Type.GetType(typeName, false);
if (type != null)
return type;
}
catch
{
}
}
return null;
}
}
}