Search code examples
c#msbuildmononuget

Resolving namespace resolution with NuGet and mono


The question: Is it possible to run mono's msbuild and force it to use specific directories as specific namespaces. Example, the namespace DevExpress could be mapped to the directory /app/MyApp/DevExpress. Or, if that's not an option, how could we make our project aware of newly installed packages with NuGet?


For a bit of context: A few years back, we inherited a (very) legacy stack of applications that included.NET applications that uses DevExpress to build a suite of 3 applications used by my client to run his events. We don't know .NET (the client was warned and accepted this, wanting to focus on his web applications), but we managed to stabilize it and have been compiling it for a few years now with PowerShell and msbuild.

We're hoping to automate a lot of this client's flow this year in an effort to save ourselves a lot of time. As part of this, we'd like to compile the .NET applications automatically on our CI server and push zipped files ready to be deployed whenever the client needs a new installation.

The project did not originally use NuGet, but to automate all this, we thought we could setup a Docker container with mono, use nuget to pull dependencies and then compile.

Sadly, we're currently hitting a stump since namespace resolution does not seem to work.

"/app/MyApp/MyApp.csproj" (default target) (1) ->
"/app/DataAccessLayer/DataAccessLayer.csproj" (default target) (3:2) ->
(CoreCompile target) -> 
  xp Server Objects/dbo_CITY.cs(6,7): error CS0246: The type or namespace name 'DevExpress' could not be found (are you missing a using directive or an assembly reference?) [/app/DataAccessLayer/DataAccessLayer.csproj]

Edit: I marked zivkan's answer as correct since while it didn't give me a solution I could go and implement, it gave me (and hopefully this question) a lot of useful information to move forward.


Solution

  • Building .NET projects doesn't work like that (look in path x for namespace y). Instead, the compiler is given a list of dlls to reference, in addition to the source files, and the compiler scans the metadata of all the references to see what namesspaces/classes are available. I believe that Java works much the same way, with jar files, although I've never done anything serious in Java.

    The way it usually works is you use Visual Studio (or another IDE that knows about .NET) and use the integrated tools to add a NuGet package to the project, as seen in the install a package with Visual Studio quickstart docs. If you use .NET Core, you can use dotnet add package <package id from the command line. This modifies the project file (.csproj), so the build system knows about it (if you use PackageReference, then it's simple enough to edit the csproj directly yourself, but if using packages.config you absolutely need tooling to do it for you).

    Then the CI build process is to first download nuget.exe then run nuget.exe restore, followed by building the project, or when using .NET Core run dotnet restore and dotnet build (since .NET Core 2.0 restore happens automatically as part of build, so it's no longer necessary to do separate steps). This is also another advantage of using .NET Core, no longer needing to download nuget.exe just to restore, finally NuGet is built into the build system (technically I think non-SDK style projects can do it too with PackageReference and msbuild -restore).

    The fact that you get the error message about the missing namespace tells me possibly that you haven't run nuget restore on the CI machine, or maybe you haven't used NuGet in the usual way.