Use JsonTextReader in DependencyContextJsonReader (#3972)
Using low level JsonTextReader in DependencyContextJsonReader class for performance reasons
This commit is contained in:
parent
01283e3df9
commit
ee6063b12b
3 changed files with 599 additions and 208 deletions
|
@ -6,7 +6,6 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyModel
|
namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
|
@ -20,16 +19,15 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(stream));
|
throw new ArgumentNullException(nameof(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
using (var streamReader = new StreamReader(stream))
|
using (var streamReader = new StreamReader(stream))
|
||||||
{
|
{
|
||||||
using (var reader = new JsonTextReader(streamReader))
|
using (var reader = new JsonTextReader(streamReader))
|
||||||
{
|
{
|
||||||
var root = JObject.Load(reader);
|
return Read(reader);
|
||||||
return Read(root);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
@ -43,81 +41,77 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsRuntimeTarget(string name) => name.Contains(DependencyContextStrings.VersionSeperator);
|
private DependencyContext Read(JsonTextReader reader)
|
||||||
|
|
||||||
private DependencyContext Read(JObject root)
|
|
||||||
{
|
{
|
||||||
var runtime = string.Empty;
|
var runtime = string.Empty;
|
||||||
var target = string.Empty;
|
var framework = string.Empty;
|
||||||
var isPortable = true;
|
var isPortable = true;
|
||||||
string runtimeTargetName = null;
|
string runtimeTargetName = null;
|
||||||
string runtimeSignature = null;
|
string runtimeSignature = null;
|
||||||
|
|
||||||
var runtimeTargetInfo = root[DependencyContextStrings.RuntimeTargetPropertyName];
|
reader.ReadStartObject();
|
||||||
|
|
||||||
// This fallback is temporary
|
CompilationOptions compilationOptions = null;
|
||||||
if (runtimeTargetInfo is JValue)
|
List<Target> targets = null;
|
||||||
|
Dictionary<string, LibraryStub> libraryStubs = null;
|
||||||
|
List<RuntimeFallbacks> runtimeFallbacks = null;
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
{
|
{
|
||||||
runtimeTargetName = runtimeTargetInfo.Value<string>();
|
switch ((string)reader.Value)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var runtimeTargetObject = (JObject) runtimeTargetInfo;
|
|
||||||
runtimeTargetName = runtimeTargetObject?[DependencyContextStrings.RuntimeTargetNamePropertyName]?.Value<string>();
|
|
||||||
runtimeSignature = runtimeTargetObject?[DependencyContextStrings.RuntimeTargetSignaturePropertyName]?.Value<string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
var libraryStubs = ReadLibraryStubs((JObject)root[DependencyContextStrings.LibrariesPropertyName]);
|
|
||||||
var targetsObject = (JObject)root[DependencyContextStrings.TargetsPropertyName];
|
|
||||||
|
|
||||||
JObject runtimeTarget = null;
|
|
||||||
JObject compileTarget = null;
|
|
||||||
|
|
||||||
if (targetsObject == null)
|
|
||||||
{
|
|
||||||
throw new FormatException("Dependency file does not have 'targets' section");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(runtimeTargetName))
|
|
||||||
{
|
|
||||||
runtimeTarget = (JObject)targetsObject[runtimeTargetName];
|
|
||||||
if (runtimeTarget == null)
|
|
||||||
{
|
{
|
||||||
throw new FormatException($"Target with name {runtimeTargetName} not found");
|
case DependencyContextStrings.RuntimeTargetPropertyName:
|
||||||
|
ReadRuntimeTarget(reader, out runtimeTargetName, out runtimeSignature);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.CompilationOptionsPropertName:
|
||||||
|
compilationOptions = ReadCompilationOptions(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.TargetsPropertyName:
|
||||||
|
targets = ReadTargets(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.LibrariesPropertyName:
|
||||||
|
libraryStubs = ReadLibraries(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.RuntimesPropertyName:
|
||||||
|
runtimeFallbacks = ReadRuntimes(reader);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
var runtimeTargetProperty = targetsObject.Properties()
|
|
||||||
.FirstOrDefault(p => IsRuntimeTarget(p.Name));
|
|
||||||
|
|
||||||
runtimeTarget = (JObject)runtimeTargetProperty?.Value;
|
if (compilationOptions == null)
|
||||||
runtimeTargetName = runtimeTargetProperty?.Name;
|
{
|
||||||
|
compilationOptions = CompilationOptions.Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Target runtimeTarget = SelectRuntimeTarget(targets, runtimeTargetName);
|
||||||
|
runtimeTargetName = runtimeTarget?.Name;
|
||||||
|
|
||||||
if (runtimeTargetName != null)
|
if (runtimeTargetName != null)
|
||||||
{
|
{
|
||||||
var seperatorIndex = runtimeTargetName.IndexOf(DependencyContextStrings.VersionSeperator);
|
var seperatorIndex = runtimeTargetName.IndexOf(DependencyContextStrings.VersionSeperator);
|
||||||
if (seperatorIndex > -1 && seperatorIndex < runtimeTargetName.Length)
|
if (seperatorIndex > -1 && seperatorIndex < runtimeTargetName.Length)
|
||||||
{
|
{
|
||||||
runtime = runtimeTargetName.Substring(seperatorIndex + 1);
|
runtime = runtimeTargetName.Substring(seperatorIndex + 1);
|
||||||
target = runtimeTargetName.Substring(0, seperatorIndex);
|
framework = runtimeTargetName.Substring(0, seperatorIndex);
|
||||||
isPortable = false;
|
isPortable = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
target = runtimeTargetName;
|
framework = runtimeTargetName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var ridlessTargetProperty = targetsObject.Properties().FirstOrDefault(p => !IsRuntimeTarget(p.Name));
|
Target compileTarget = null;
|
||||||
if (ridlessTargetProperty != null)
|
|
||||||
|
var ridlessTarget = targets.FirstOrDefault(t => !IsRuntimeTarget(t.Name));
|
||||||
|
if (ridlessTarget != null)
|
||||||
{
|
{
|
||||||
compileTarget = (JObject)ridlessTargetProperty.Value;
|
compileTarget = ridlessTarget;
|
||||||
if (runtimeTarget == null)
|
if (runtimeTarget == null)
|
||||||
{
|
{
|
||||||
runtimeTarget = compileTarget;
|
runtimeTarget = compileTarget;
|
||||||
target = ridlessTargetProperty.Name;
|
framework = ridlessTarget.Name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,65 +121,445 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
}
|
}
|
||||||
|
|
||||||
return new DependencyContext(
|
return new DependencyContext(
|
||||||
new TargetInfo(target, runtime, runtimeSignature, isPortable),
|
new TargetInfo(framework, runtime, runtimeSignature, isPortable),
|
||||||
ReadCompilationOptions((JObject)root[DependencyContextStrings.CompilationOptionsPropertName]),
|
compilationOptions,
|
||||||
ReadLibraries(compileTarget, false, libraryStubs).Cast<CompilationLibrary>().ToArray(),
|
CreateLibraries(compileTarget?.Libraries, false, libraryStubs).Cast<CompilationLibrary>().ToArray(),
|
||||||
ReadLibraries(runtimeTarget, true, libraryStubs).Cast<RuntimeLibrary>().ToArray(),
|
CreateLibraries(runtimeTarget.Libraries, true, libraryStubs).Cast<RuntimeLibrary>().ToArray(),
|
||||||
ReadRuntimeGraph((JObject)root[DependencyContextStrings.RuntimesPropertyName]).ToArray()
|
runtimeFallbacks ?? Enumerable.Empty<RuntimeFallbacks>());
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<RuntimeFallbacks> ReadRuntimeGraph(JObject runtimes)
|
private Target SelectRuntimeTarget(List<Target> targets, string runtimeTargetName)
|
||||||
{
|
{
|
||||||
if (runtimes == null)
|
Target target;
|
||||||
|
|
||||||
|
if (targets == null || targets.Count == 0)
|
||||||
{
|
{
|
||||||
yield break;
|
throw new FormatException("Dependency file does not have 'targets' section");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var pair in runtimes)
|
if (!string.IsNullOrEmpty(runtimeTargetName))
|
||||||
{
|
{
|
||||||
yield return new RuntimeFallbacks(pair.Key, pair.Value.Values<string>().ToArray());
|
target = targets.FirstOrDefault(t => t.Name == runtimeTargetName);
|
||||||
|
if (target == null)
|
||||||
|
{
|
||||||
|
throw new FormatException($"Target with name {runtimeTargetName} not found");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
target = targets.FirstOrDefault(t => IsRuntimeTarget(t.Name));
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompilationOptions ReadCompilationOptions(JObject compilationOptionsObject)
|
private bool IsRuntimeTarget(string name)
|
||||||
{
|
{
|
||||||
if (compilationOptionsObject == null)
|
return name.Contains(DependencyContextStrings.VersionSeperator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadRuntimeTarget(JsonTextReader reader, out string runtimeTargetName, out string runtimeSignature)
|
||||||
|
{
|
||||||
|
runtimeTargetName = null;
|
||||||
|
runtimeSignature = null;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
string propertyName;
|
||||||
|
string propertyValue;
|
||||||
|
while (reader.TryReadStringProperty(out propertyName, out propertyValue))
|
||||||
{
|
{
|
||||||
return CompilationOptions.Default;
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case DependencyContextStrings.RuntimeTargetNamePropertyName:
|
||||||
|
runtimeTargetName = propertyValue;
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.RuntimeTargetSignaturePropertyName:
|
||||||
|
runtimeSignature = propertyValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException($"Unknown property name '{propertyName}'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompilationOptions ReadCompilationOptions(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
IEnumerable<string> defines = null;
|
||||||
|
string languageVersion = null;
|
||||||
|
string platform = null;
|
||||||
|
bool? allowUnsafe = null;
|
||||||
|
bool? warningsAsErrors = null;
|
||||||
|
bool? optimize = null;
|
||||||
|
string keyFile = null;
|
||||||
|
bool? delaySign = null;
|
||||||
|
bool? publicSign = null;
|
||||||
|
string debugType = null;
|
||||||
|
bool? emitEntryPoint = null;
|
||||||
|
bool? generateXmlDocumentation = null;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
switch ((string)reader.Value)
|
||||||
|
{
|
||||||
|
case DependencyContextStrings.DefinesPropertyName:
|
||||||
|
defines = reader.ReadStringArray();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.LanguageVersionPropertyName:
|
||||||
|
languageVersion = reader.ReadAsString();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.PlatformPropertyName:
|
||||||
|
platform = reader.ReadAsString();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.AllowUnsafePropertyName:
|
||||||
|
allowUnsafe = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.WarningsAsErrorsPropertyName:
|
||||||
|
warningsAsErrors = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.OptimizePropertyName:
|
||||||
|
optimize = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.KeyFilePropertyName:
|
||||||
|
keyFile = reader.ReadAsString();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.DelaySignPropertyName:
|
||||||
|
delaySign = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.PublicSignPropertyName:
|
||||||
|
publicSign = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.DebugTypePropertyName:
|
||||||
|
debugType = reader.ReadAsString();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.EmitEntryPointPropertyName:
|
||||||
|
emitEntryPoint = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.GenerateXmlDocumentationPropertyName:
|
||||||
|
generateXmlDocumentation = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException($"Unknown property name '{reader.Value}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
return new CompilationOptions(
|
return new CompilationOptions(
|
||||||
compilationOptionsObject[DependencyContextStrings.DefinesPropertyName]?.Values<string>().ToArray() ?? Enumerable.Empty<string>(),
|
defines ?? Enumerable.Empty<string>(),
|
||||||
// ToArray is here to prevent IEnumerable<string> holding to json object graph
|
languageVersion,
|
||||||
compilationOptionsObject[DependencyContextStrings.LanguageVersionPropertyName]?.Value<string>(),
|
platform,
|
||||||
compilationOptionsObject[DependencyContextStrings.PlatformPropertyName]?.Value<string>(),
|
allowUnsafe,
|
||||||
compilationOptionsObject[DependencyContextStrings.AllowUnsafePropertyName]?.Value<bool>(),
|
warningsAsErrors,
|
||||||
compilationOptionsObject[DependencyContextStrings.WarningsAsErrorsPropertyName]?.Value<bool>(),
|
optimize,
|
||||||
compilationOptionsObject[DependencyContextStrings.OptimizePropertyName]?.Value<bool>(),
|
keyFile,
|
||||||
compilationOptionsObject[DependencyContextStrings.KeyFilePropertyName]?.Value<string>(),
|
delaySign,
|
||||||
compilationOptionsObject[DependencyContextStrings.DelaySignPropertyName]?.Value<bool>(),
|
publicSign,
|
||||||
compilationOptionsObject[DependencyContextStrings.PublicSignPropertyName]?.Value<bool>(),
|
debugType,
|
||||||
compilationOptionsObject[DependencyContextStrings.DebugTypePropertyName]?.Value<string>(),
|
emitEntryPoint,
|
||||||
compilationOptionsObject[DependencyContextStrings.EmitEntryPointPropertyName]?.Value<bool>(),
|
generateXmlDocumentation);
|
||||||
compilationOptionsObject[DependencyContextStrings.GenerateXmlDocumentationPropertyName]?.Value<bool>()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<Library> ReadLibraries(JObject librariesObject, bool runtime, Dictionary<string, LibraryStub> libraryStubs)
|
private List<Target> ReadTargets(JsonTextReader reader)
|
||||||
{
|
{
|
||||||
if (librariesObject == null)
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
var targets = new List<Target>();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
targets.Add(ReadTarget(reader, (string)reader.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Target ReadTarget(JsonTextReader reader, string targetName)
|
||||||
|
{
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
var libraries = new List<TargetLibrary>();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
libraries.Add(ReadTargetLibrary(reader, (string)reader.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return new Target()
|
||||||
|
{
|
||||||
|
Name = targetName,
|
||||||
|
Libraries = libraries
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private TargetLibrary ReadTargetLibrary(JsonTextReader reader, string targetLibraryName)
|
||||||
|
{
|
||||||
|
IEnumerable<Dependency> dependencies = null;
|
||||||
|
List<string> runtimes = null;
|
||||||
|
List<string> natives = null;
|
||||||
|
List<string> compilations = null;
|
||||||
|
List<RuntimeTargetEntryStub> runtimeTargets = null;
|
||||||
|
List<ResourceAssembly> resources = null;
|
||||||
|
bool? compileOnly = null;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
switch ((string)reader.Value)
|
||||||
|
{
|
||||||
|
case DependencyContextStrings.DependenciesPropertyName:
|
||||||
|
dependencies = ReadTargetLibraryDependencies(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.RuntimeAssembliesKey:
|
||||||
|
runtimes = ReadPropertyNames(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.NativeLibrariesKey:
|
||||||
|
natives = ReadPropertyNames(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.CompileTimeAssembliesKey:
|
||||||
|
compilations = ReadPropertyNames(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.RuntimeTargetsPropertyName:
|
||||||
|
runtimeTargets = ReadTargetLibraryRuntimeTargets(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.ResourceAssembliesPropertyName:
|
||||||
|
resources = ReadTargetLibraryResources(reader);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.CompilationOnlyPropertyName:
|
||||||
|
compileOnly = reader.ReadAsBoolean();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException($"Unknown property name '{reader.Value}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return new TargetLibrary()
|
||||||
|
{
|
||||||
|
Name = targetLibraryName,
|
||||||
|
Dependencies = dependencies ?? Enumerable.Empty<Dependency>(),
|
||||||
|
Runtimes = runtimes,
|
||||||
|
Natives = natives,
|
||||||
|
Compilations = compilations,
|
||||||
|
RuntimeTargets = runtimeTargets,
|
||||||
|
Resources = resources,
|
||||||
|
CompileOnly = compileOnly
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<Dependency> ReadTargetLibraryDependencies(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
var dependencies = new List<Dependency>();
|
||||||
|
string name;
|
||||||
|
string version;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.TryReadStringProperty(out name, out version))
|
||||||
|
{
|
||||||
|
dependencies.Add(new Dependency(Pool(name), Pool(version)));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<string> ReadPropertyNames(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
var runtimes = new List<string>();
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
var libraryName = (string)reader.Value;
|
||||||
|
reader.Skip();
|
||||||
|
|
||||||
|
runtimes.Add(libraryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return runtimes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RuntimeTargetEntryStub> ReadTargetLibraryRuntimeTargets(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
var runtimeTargets = new List<RuntimeTargetEntryStub>();
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
var runtimeTarget = new RuntimeTargetEntryStub();
|
||||||
|
runtimeTarget.Path = (string)reader.Value;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
string propertyName;
|
||||||
|
string propertyValue;
|
||||||
|
while (reader.TryReadStringProperty(out propertyName, out propertyValue))
|
||||||
|
{
|
||||||
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case DependencyContextStrings.RidPropertyName:
|
||||||
|
runtimeTarget.Rid = Pool(propertyValue);
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.AssetTypePropertyName:
|
||||||
|
runtimeTarget.Type = Pool(propertyValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException($"Unknown property name '{propertyName}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
runtimeTargets.Add(runtimeTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return runtimeTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ResourceAssembly> ReadTargetLibraryResources(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
var resources = new List<ResourceAssembly>();
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
var path = (string)reader.Value;
|
||||||
|
string locale = null;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
string propertyName;
|
||||||
|
string propertyValue;
|
||||||
|
|
||||||
|
while (reader.TryReadStringProperty(out propertyName, out propertyValue))
|
||||||
|
{
|
||||||
|
if (propertyName == DependencyContextStrings.LocalePropertyName)
|
||||||
|
{
|
||||||
|
locale = propertyValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
if (locale != null)
|
||||||
|
{
|
||||||
|
resources.Add(new ResourceAssembly(path, Pool(locale)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return resources;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, LibraryStub> ReadLibraries(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
var libraries = new Dictionary<string, LibraryStub>();
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
var libraryName = (string)reader.Value;
|
||||||
|
|
||||||
|
libraries.Add(Pool(libraryName), ReadOneLibrary(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return libraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LibraryStub ReadOneLibrary(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
string hash = null;
|
||||||
|
string type = null;
|
||||||
|
bool serviceable = false;
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
switch ((string)reader.Value)
|
||||||
|
{
|
||||||
|
case DependencyContextStrings.Sha512PropertyName:
|
||||||
|
hash = reader.ReadAsString();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.TypePropertyName:
|
||||||
|
type = reader.ReadAsString();
|
||||||
|
break;
|
||||||
|
case DependencyContextStrings.ServiceablePropertyName:
|
||||||
|
serviceable = reader.ReadAsBoolean().GetValueOrDefault(false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new FormatException($"Unknown property name '{reader.Value}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return new LibraryStub()
|
||||||
|
{
|
||||||
|
Hash = hash,
|
||||||
|
Type = Pool(type),
|
||||||
|
Serviceable = serviceable
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RuntimeFallbacks> ReadRuntimes(JsonTextReader reader)
|
||||||
|
{
|
||||||
|
var runtimeFallbacks = new List<RuntimeFallbacks>();
|
||||||
|
|
||||||
|
reader.ReadStartObject();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
var runtime = (string)reader.Value;
|
||||||
|
var fallbacks = reader.ReadStringArray();
|
||||||
|
|
||||||
|
runtimeFallbacks.Add(new RuntimeFallbacks(runtime, fallbacks));
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.CheckEndObject();
|
||||||
|
|
||||||
|
return runtimeFallbacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Library> CreateLibraries(IEnumerable<TargetLibrary> libraries, bool runtime, Dictionary<string, LibraryStub> libraryStubs)
|
||||||
|
{
|
||||||
|
if (libraries == null)
|
||||||
{
|
{
|
||||||
return Enumerable.Empty<Library>();
|
return Enumerable.Empty<Library>();
|
||||||
}
|
}
|
||||||
return librariesObject.Properties()
|
return libraries
|
||||||
.Select(property => ReadLibrary(property, runtime, libraryStubs))
|
.Select(property => CreateLibrary(property, runtime, libraryStubs))
|
||||||
.Where(library => library != null);
|
.Where(library => library != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Library ReadLibrary(JProperty property, bool runtime, Dictionary<string, LibraryStub> libraryStubs)
|
private Library CreateLibrary(TargetLibrary targetLibrary, bool runtime, Dictionary<string, LibraryStub> libraryStubs)
|
||||||
{
|
{
|
||||||
var nameWithVersion = property.Name;
|
var nameWithVersion = targetLibrary.Name;
|
||||||
LibraryStub stub;
|
LibraryStub stub;
|
||||||
|
|
||||||
if (!libraryStubs.TryGetValue(nameWithVersion, out stub))
|
if (!libraryStubs.TryGetValue(nameWithVersion, out stub))
|
||||||
|
@ -198,68 +572,57 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
var name = Pool(nameWithVersion.Substring(0, seperatorPosition));
|
var name = Pool(nameWithVersion.Substring(0, seperatorPosition));
|
||||||
var version = Pool(nameWithVersion.Substring(seperatorPosition + 1));
|
var version = Pool(nameWithVersion.Substring(seperatorPosition + 1));
|
||||||
|
|
||||||
var libraryObject = (JObject)property.Value;
|
|
||||||
|
|
||||||
var dependencies = ReadDependencies(libraryObject);
|
|
||||||
|
|
||||||
if (runtime)
|
if (runtime)
|
||||||
{
|
{
|
||||||
// Runtime section of this library was trimmed by type:platform
|
// Runtime section of this library was trimmed by type:platform
|
||||||
var isCompilationOnly = libraryObject.Value<bool?>(DependencyContextStrings.CompilationOnlyPropertyName);
|
var isCompilationOnly = targetLibrary.CompileOnly;
|
||||||
if (isCompilationOnly == true)
|
if (isCompilationOnly == true)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var runtimeTargetsObject = (JObject)libraryObject[DependencyContextStrings.RuntimeTargetsPropertyName];
|
|
||||||
|
|
||||||
var entries = ReadRuntimeTargetEntries(runtimeTargetsObject).ToArray();
|
|
||||||
|
|
||||||
var runtimeAssemblyGroups = new List<RuntimeAssetGroup>();
|
var runtimeAssemblyGroups = new List<RuntimeAssetGroup>();
|
||||||
var nativeLibraryGroups = new List<RuntimeAssetGroup>();
|
var nativeLibraryGroups = new List<RuntimeAssetGroup>();
|
||||||
foreach (var ridGroup in entries.GroupBy(e => e.Rid))
|
if (targetLibrary.RuntimeTargets != null)
|
||||||
{
|
{
|
||||||
var groupRuntimeAssemblies = ridGroup
|
foreach (var ridGroup in targetLibrary.RuntimeTargets.GroupBy(e => e.Rid))
|
||||||
.Where(e => e.Type == DependencyContextStrings.RuntimeAssetType)
|
|
||||||
.Select(e => e.Path)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
if (groupRuntimeAssemblies.Any())
|
|
||||||
{
|
{
|
||||||
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(
|
var groupRuntimeAssemblies = ridGroup
|
||||||
ridGroup.Key,
|
.Where(e => e.Type == DependencyContextStrings.RuntimeAssetType)
|
||||||
groupRuntimeAssemblies.Where(a => Path.GetFileName(a) != "_._")));
|
.Select(e => e.Path)
|
||||||
}
|
.ToArray();
|
||||||
|
|
||||||
var groupNativeLibraries = ridGroup
|
if (groupRuntimeAssemblies.Any())
|
||||||
.Where(e => e.Type == DependencyContextStrings.NativeAssetType)
|
{
|
||||||
.Select(e => e.Path)
|
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(
|
||||||
.ToArray();
|
ridGroup.Key,
|
||||||
|
groupRuntimeAssemblies.Where(a => Path.GetFileName(a) != "_._")));
|
||||||
|
}
|
||||||
|
|
||||||
if (groupNativeLibraries.Any())
|
var groupNativeLibraries = ridGroup
|
||||||
{
|
.Where(e => e.Type == DependencyContextStrings.NativeAssetType)
|
||||||
nativeLibraryGroups.Add(new RuntimeAssetGroup(
|
.Select(e => e.Path)
|
||||||
ridGroup.Key,
|
.ToArray();
|
||||||
groupNativeLibraries.Where(a => Path.GetFileName(a) != "_._")));
|
|
||||||
|
if (groupNativeLibraries.Any())
|
||||||
|
{
|
||||||
|
nativeLibraryGroups.Add(new RuntimeAssetGroup(
|
||||||
|
ridGroup.Key,
|
||||||
|
groupNativeLibraries.Where(a => Path.GetFileName(a) != "_._")));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var runtimeAssemblies = ReadAssetList(libraryObject, DependencyContextStrings.RuntimeAssembliesKey)
|
if (targetLibrary.Runtimes != null && targetLibrary.Runtimes.Count > 0)
|
||||||
.ToArray();
|
|
||||||
if (runtimeAssemblies.Any())
|
|
||||||
{
|
{
|
||||||
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, runtimeAssemblies));
|
runtimeAssemblyGroups.Add(new RuntimeAssetGroup(string.Empty, targetLibrary.Runtimes));
|
||||||
}
|
}
|
||||||
|
|
||||||
var nativeLibraries = ReadAssetList(libraryObject, DependencyContextStrings.NativeLibrariesKey)
|
if (targetLibrary.Natives != null && targetLibrary.Natives.Count > 0)
|
||||||
.ToArray();
|
|
||||||
if(nativeLibraries.Any())
|
|
||||||
{
|
{
|
||||||
nativeLibraryGroups.Add(new RuntimeAssetGroup(string.Empty, nativeLibraries));
|
nativeLibraryGroups.Add(new RuntimeAssetGroup(string.Empty, targetLibrary.Natives));
|
||||||
}
|
}
|
||||||
|
|
||||||
var resourceAssemblies = ReadResourceAssemblies((JObject)libraryObject[DependencyContextStrings.ResourceAssembliesPropertyName]);
|
|
||||||
|
|
||||||
return new RuntimeLibrary(
|
return new RuntimeLibrary(
|
||||||
type: stub.Type,
|
type: stub.Type,
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -267,96 +630,17 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
hash: stub.Hash,
|
hash: stub.Hash,
|
||||||
runtimeAssemblyGroups: runtimeAssemblyGroups,
|
runtimeAssemblyGroups: runtimeAssemblyGroups,
|
||||||
nativeLibraryGroups: nativeLibraryGroups,
|
nativeLibraryGroups: nativeLibraryGroups,
|
||||||
resourceAssemblies: resourceAssemblies,
|
resourceAssemblies: targetLibrary.Resources ?? Enumerable.Empty<ResourceAssembly>(),
|
||||||
dependencies: dependencies,
|
dependencies: targetLibrary.Dependencies,
|
||||||
serviceable: stub.Serviceable);
|
serviceable: stub.Serviceable);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var assemblies = ReadAssetList(libraryObject, DependencyContextStrings.CompileTimeAssembliesKey);
|
var assemblies = (targetLibrary.Compilations != null) ? targetLibrary.Compilations : Enumerable.Empty<string>();
|
||||||
return new CompilationLibrary(stub.Type, name, version, stub.Hash, assemblies, dependencies, stub.Serviceable);
|
return new CompilationLibrary(stub.Type, name, version, stub.Hash, assemblies, targetLibrary.Dependencies, stub.Serviceable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ResourceAssembly> ReadResourceAssemblies(JObject resourcesObject)
|
|
||||||
{
|
|
||||||
if (resourcesObject == null)
|
|
||||||
{
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
foreach (var resourceProperty in resourcesObject)
|
|
||||||
{
|
|
||||||
yield return new ResourceAssembly(
|
|
||||||
locale: Pool(resourceProperty.Value[DependencyContextStrings.LocalePropertyName]?.Value<string>()),
|
|
||||||
path: resourceProperty.Key
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<RuntimeTargetEntryStub> ReadRuntimeTargetEntries(JObject runtimeTargetObject)
|
|
||||||
{
|
|
||||||
if (runtimeTargetObject == null)
|
|
||||||
{
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
foreach (var libraryProperty in runtimeTargetObject)
|
|
||||||
{
|
|
||||||
var libraryObject = (JObject)libraryProperty.Value;
|
|
||||||
yield return new RuntimeTargetEntryStub()
|
|
||||||
{
|
|
||||||
Path = libraryProperty.Key,
|
|
||||||
Rid = Pool(libraryObject[DependencyContextStrings.RidPropertyName].Value<string>()),
|
|
||||||
Type = Pool(libraryObject[DependencyContextStrings.AssetTypePropertyName].Value<string>())
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string[] ReadAssetList(JObject libraryObject, string name)
|
|
||||||
{
|
|
||||||
var assembliesObject = (JObject)libraryObject[name];
|
|
||||||
|
|
||||||
if (assembliesObject == null)
|
|
||||||
{
|
|
||||||
return new string[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return assembliesObject.Properties().Select(property => property.Name).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dependency[] ReadDependencies(JObject libraryObject)
|
|
||||||
{
|
|
||||||
var dependenciesObject = (JObject)libraryObject[DependencyContextStrings.DependenciesPropertyName];
|
|
||||||
|
|
||||||
if (dependenciesObject == null)
|
|
||||||
{
|
|
||||||
return new Dependency[] { };
|
|
||||||
}
|
|
||||||
|
|
||||||
return dependenciesObject.Properties()
|
|
||||||
.Select(property => new Dependency(Pool(property.Name), Pool((string)property.Value))).ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Dictionary<string, LibraryStub> ReadLibraryStubs(JObject librariesObject)
|
|
||||||
{
|
|
||||||
var libraries = new Dictionary<string, LibraryStub>();
|
|
||||||
if (librariesObject != null)
|
|
||||||
{
|
|
||||||
foreach (var libraryProperty in librariesObject)
|
|
||||||
{
|
|
||||||
var value = (JObject)libraryProperty.Value;
|
|
||||||
var stub = new LibraryStub
|
|
||||||
{
|
|
||||||
Name = Pool(libraryProperty.Key),
|
|
||||||
Hash = value[DependencyContextStrings.Sha512PropertyName]?.Value<string>(),
|
|
||||||
Type = Pool(value[DependencyContextStrings.TypePropertyName].Value<string>()),
|
|
||||||
Serviceable = value[DependencyContextStrings.ServiceablePropertyName]?.Value<bool>() == true
|
|
||||||
};
|
|
||||||
libraries.Add(stub.Name, stub);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return libraries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string Pool(string s)
|
private string Pool(string s)
|
||||||
{
|
{
|
||||||
if (s == null)
|
if (s == null)
|
||||||
|
@ -373,17 +657,43 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class Target
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
public IEnumerable<TargetLibrary> Libraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct TargetLibrary
|
||||||
|
{
|
||||||
|
public string Name;
|
||||||
|
|
||||||
|
public IEnumerable<Dependency> Dependencies;
|
||||||
|
|
||||||
|
public List<string> Runtimes;
|
||||||
|
|
||||||
|
public List<string> Natives;
|
||||||
|
|
||||||
|
public List<string> Compilations;
|
||||||
|
|
||||||
|
public List<RuntimeTargetEntryStub> RuntimeTargets;
|
||||||
|
|
||||||
|
public List<ResourceAssembly> Resources;
|
||||||
|
|
||||||
|
public bool? CompileOnly;
|
||||||
|
}
|
||||||
|
|
||||||
private struct RuntimeTargetEntryStub
|
private struct RuntimeTargetEntryStub
|
||||||
{
|
{
|
||||||
public string Type;
|
public string Type;
|
||||||
|
|
||||||
public string Path;
|
public string Path;
|
||||||
|
|
||||||
public string Rid;
|
public string Rid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct LibraryStub
|
private struct LibraryStub
|
||||||
{
|
{
|
||||||
public string Name;
|
|
||||||
|
|
||||||
public string Hash;
|
public string Hash;
|
||||||
|
|
||||||
public string Type;
|
public string Type;
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.DependencyModel
|
||||||
|
{
|
||||||
|
internal static class JsonTextReaderExtensions
|
||||||
|
{
|
||||||
|
internal static bool TryReadStringProperty(this JsonTextReader reader, out string name, out string value)
|
||||||
|
{
|
||||||
|
name = null;
|
||||||
|
value = null;
|
||||||
|
if (reader.Read() && reader.TokenType == JsonToken.PropertyName)
|
||||||
|
{
|
||||||
|
name = (string)reader.Value;
|
||||||
|
value = reader.ReadAsString();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void ReadStartObject(this JsonTextReader reader)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
CheckStartObject(reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CheckStartObject(this JsonTextReader reader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonToken.StartObject)
|
||||||
|
{
|
||||||
|
throw CreateUnexpectedException(reader, "{");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static void CheckEndObject(this JsonTextReader reader)
|
||||||
|
{
|
||||||
|
if (reader.TokenType != JsonToken.EndObject)
|
||||||
|
{
|
||||||
|
throw CreateUnexpectedException(reader, "}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string[] ReadStringArray(this JsonTextReader reader)
|
||||||
|
{
|
||||||
|
reader.Read();
|
||||||
|
if (reader.TokenType != JsonToken.StartArray)
|
||||||
|
{
|
||||||
|
throw CreateUnexpectedException(reader,"[");
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = new List<string>();
|
||||||
|
|
||||||
|
while (reader.Read() && reader.TokenType == JsonToken.String)
|
||||||
|
{
|
||||||
|
items.Add((string)reader.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reader.TokenType != JsonToken.EndArray)
|
||||||
|
{
|
||||||
|
throw CreateUnexpectedException(reader, "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
return items.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Exception CreateUnexpectedException(JsonTextReader reader, string expected)
|
||||||
|
{
|
||||||
|
return new FormatException($"Unexpected character encountered, excepted '{expected}' " +
|
||||||
|
$"at line {reader.LineNumber} position {reader.LinePosition} path {reader.Path}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,7 +26,8 @@ namespace Microsoft.Extensions.DependencyModel.Tests
|
||||||
var context = Read(
|
var context = Read(
|
||||||
@"{
|
@"{
|
||||||
""runtimeTarget"": {
|
""runtimeTarget"": {
|
||||||
""name"":"".NETCoreApp,Version=v1.0/osx.10.10-x64""
|
""name"":"".NETCoreApp,Version=v1.0/osx.10.10-x64"",
|
||||||
|
""signature"":""target-signature""
|
||||||
},
|
},
|
||||||
""targets"": {
|
""targets"": {
|
||||||
"".NETCoreApp,Version=v1.0/osx.10.10-x64"": {},
|
"".NETCoreApp,Version=v1.0/osx.10.10-x64"": {},
|
||||||
|
@ -35,6 +36,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests
|
||||||
context.Target.IsPortable.Should().BeFalse();
|
context.Target.IsPortable.Should().BeFalse();
|
||||||
context.Target.Framework.Should().Be(".NETCoreApp,Version=v1.0");
|
context.Target.Framework.Should().Be(".NETCoreApp,Version=v1.0");
|
||||||
context.Target.Runtime.Should().Be("osx.10.10-x64");
|
context.Target.Runtime.Should().Be("osx.10.10-x64");
|
||||||
|
context.Target.RuntimeSignature.Should().Be("target-signature");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
@ -299,7 +301,9 @@ namespace Microsoft.Extensions.DependencyModel.Tests
|
||||||
{
|
{
|
||||||
var context = Read(
|
var context = Read(
|
||||||
@"{
|
@"{
|
||||||
""runtimeTarget"": "".NETCoreApp,Version=v1.0"",
|
""runtimeTarget"": {
|
||||||
|
""name"": "".NETCoreApp,Version=v1.0""
|
||||||
|
},
|
||||||
""targets"": {
|
""targets"": {
|
||||||
"".NETCoreApp,Version=v1.0"": {
|
"".NETCoreApp,Version=v1.0"": {
|
||||||
""System.Banana/1.0.0"": {
|
""System.Banana/1.0.0"": {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue