RicoSuter / DNT

DNT (DotNetTools): Command line tools to manage .NET projects and solutions.
MIT License
416 stars 63 forks source link

InvalidCastException when mixing "single project per package" and "multiple projects per package" #102

Closed max-win-at closed 3 years ago

max-win-at commented 3 years ago

When mixing "single project per package" and "multiple projects per package" in switcher.json eg:

{
  "solution": "MySolution.sln",
  "mappings": {
    "SimpleNuget": "../SimpleProject/SimpleProject.csproj",
    "ComplexNuget": [
      "../ComplexProject.PartA/ComplexProject.PartA.csproj",
      "../ComplexProject.PartB/ComplexProject.PartB.csproj"
    ]
  }
}

Calling dnt switch-to-projects will produce a System.InvalidCastException: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken.

I helped myself by refactoring switcher.json to the following scheme:

{
  "solution": "MySolution.sln",
  "mappings": {
    "SimpleNuget": [
      "../SimpleProject/SimpleProject.csproj"
    ],
    "ComplexNuget": [
      "../ComplexProject.PartA/ComplexProject.PartA.csproj",
      "../ComplexProject.PartB/ComplexProject.PartB.csproj"
    ]
  }
}

Using arrays with one element did the trick.

However, after replacing the package references, dnt persisted its restore information back into switcher.json. By doing so it also reverted the JArrays with one elemet back to simple JTokens.

Which means, that for the subsequent call dnt switch-to-packages, I again have to manually refactor each single project per package in switcher.json, or otherwise another System.InvalidCastException: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken. is produced.

The complete exception stack for both cases:

System.InvalidCastException: Cannot cast Newtonsoft.Json.Linq.JArray to Newtonsoft.Json.Linq.JToken.
   at Newtonsoft.Json.Linq.Extensions.Convert[T,U](T token)
   at Newtonsoft.Json.Linq.Extensions.Value[T,U](IEnumerable`1 value)
   at Newtonsoft.Json.Linq.Extensions.Value[U](IEnumerable`1 value)
   at Dnt.Commands.Packages.Switcher.SingleOrArrayConverter.<>c.<ReadJson>b__1_1(JProperty val) in C:\projects\dnt\
src\Dnt.Commands\Packages\Switcher\SingleOrArrayConvertor.cs:line 25
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 e
lementSelector, IEqualityComparer`1 comparer)
   at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 e
lementSelector)
   at Dnt.Commands.Packages.Switcher.SingleOrArrayConverter.ReadJson(JsonReader reader, Type objectType, Object exi
stingValue, JsonSerializer serializer) in C:\projects\dnt\src\Dnt.Commands\Packages\Switcher\SingleOrArrayConvertor
.cs:line 25
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, Js
onReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConver
ter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader,
Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader
, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, J
sonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, O
bject existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type object
Type, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMe
mber, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Bo
olean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
   at Dnt.Commands.Packages.Switcher.Refe   at Dnt.Commands.Packages.Switcher.ReferenceSwitcherConfiguration.Load(String fileName, IConsoleHost host) in C:\projects\dnt\src
   at Dnt.Commands.Packages.Switcher.Refe   at Dnt.Commands.Packages.Switcher.ReferenceSwitcherConfiguration.Load(String fileName, IConsoleHost host) in C:\projects\dnt\src\Dn
t.Commands\Packages\Switcher\ReferenceSw    at Dnt.Commands.Packages.Switcher.ReferenceSwitcherConfiguration.Load(String fileName, IConsoleHost host) in C:\projects\dnt\src\Dn
   at Dnt.Commands.Packages.Switcher.ReferenceSwitcherConfiguration.Load(String fileName, IConsoleHost host) in C:\projects\dnt\src\Dnt.Commands\Packages\Switcher\ReferenceSwit
cherConfiguration.cs:line 43
   at Dnt.Commands.Packages.SwitchPackagesToProjectsCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in C:\projects\dnt\src\Dnt.Commands\Packages\SwitchPacka
gesToProjectsCommand.cs:line 22
   at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
   at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
   at NConsole.CommandLineProcessor.Process(String[] args, Object input)
   at Dnt.Program.Main(String[] args) in C:\projects\dnt\src\Dnt\Program.cs:line 33
max-win-at commented 3 years ago

A quickfix that relies on msbuild's fault tolerance is:

{
  "solution": "MySolution.sln",
  "mappings": {
    "SimpleNuget": [
      "../SimpleProject/SimpleProject.csproj",
      "../SimpleProject/SimpleProject.csproj"
    ],
    "ComplexNuget": [
      "../ComplexProject.PartA/ComplexProject.PartA.csproj",
      "../ComplexProject.PartB/ComplexProject.PartB.csproj"
    ]
  }
}