Given following source code which need to be maintained within a class library project:
using Newtonsoft.Json;
namespace Zephyr.SharedProject.Core
{
public class TestClass
{
public TestClass()
{
string json = JsonConvert.SerializeObject(new
{
PropertyA = 1
});
}
}
}
What are the options do we have if our class library need to support different versions of Newtonsoft.Json?
For example, it was known that the product which consumes the class library have following dependencies:
Product version
Newtonsoft.Json version
1
10.0.1
2
11.0.1
3
12.0.1
Assuming Newtonsoft.Json does not introduce breaking change and same source code can be used with all version above, how would one create and maintain Visual Studio solution to support scenarios above?
I'm thinking having a single project which holds the source code and creating each version-specific project by adding the source code as link1 with corresponding dependencies which looks like following:
Solution
Core Project references Newtonsoft.Json v???
TestClass (source code)
Project_v1 references Newtonsoft.Json v10.0.1
TestClass (added as link)
Project_v2 references Newtonsoft.Json v11.0.1
TestClass (added as link)
Project_v3 references Newtonsoft.Json v12.0.1
TestClass (added as link)
1Right click project, Add > Existing Item > Add As Link
Having project structure above would allow us to maintain a single file and each project can have their own dependency which is fine where we can have unit test for each project as well.
However I'm in dilemma to define the dependency on Core Project as it's ambiguous and would shows compilation error in Visual Studio due to missing reference.
I'm aware binding redirect would solve the problem at consumer-side for version mismatch but I'm interested with the solution from producer (class library) perspective, kindly enlighten me if there's any better approach, cheers!
A shared project can be created in Microsoft Visual Studio which acts a central repository that contains the source codes or files.
The project itself doesn't require any references which can then be added as reference for version specific projects.
When open the source code in editor, one can easily switch between the context of referenced projects to make sure everything's good in case there are any conflict due to different dependencies.
The final project structure would then looks similar to:
Product version
Project type
Newtonsoft.Json version
All
Shared
N/A
1
Class library
10.0.1
2
Class library
11.0.1
3
Class library
12.0.1
P/S: This feature has been around for quite some time and I just recently found out about it, hopefully the information provided helps!
Extra: channel 9 video - Sharing Code Across Platforms With Visual Studio 2015
I recently use Roslyn to compile and execute code at the runtime of a game application. Thank to some useful ressource such as this web site and Vendettamit answer, I manage to code a program on a C# Console Net Core project on window 10 which execute this code located in a txt file at the root of the application.
using System;
namespace Test15
{
public class Program
{
public static int Main()
{
System.Console.WriteLine("Hello World from external Dll !");
System.Console.WriteLine("And it work !");
return 10;
}
}
}
I'm not going to share code because it is really similar to Vendettamit answer, and this program work well on a C# Console Net Core project on window 10.
So next step, I try to make this program work with the C# Monogame Framework on a Android project which use Xamarin.
First problem : when trying to add the nugget package "Microsoft.CodeAnalysis" which seem necessary for Roslyn, I have the 2 following error :
Unable to resolve reference 'Humanizer', referenced by `Microsoft.CodeAnalysis.CSharp.Workspaces`.
Add NuGet package or assembly reference for 'Humanizer', or remove the reference to
'Microsoft.CodeAnalysis.CSharp.Workspaces'. Game2
Unable to resolve reference 'SQLitePCLRaw.core', referenced by `Microsoft.CodeAnalysis.Workspaces`.
Add NuGet package or assembly reference for 'SQLitePCLRaw.core', or remove the reference to
'Microsoft.CodeAnalysis.Workspaces'. Game2
(Translated from French)
When replacing the "Microsoft.CodeAnalysis" nugget package by "microsoft.CodeAnalysis.CSharp", both errors disappears.
However at the runtime, adding the MetadataReference don't work.
For instance in the Console project I use :
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location);
To add a MetadataReference to mscorlib.dll, but on an Android project, it crash because typeof(object).GetTypeInfo().Assembly.Location return "mscorlib.dll" instead of somethings like "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\3.1.9\System.Private.CoreLib.dll", because we are on Android I guess. (same with other MetadataReference )
So when calling the method CSharpCompilation.Create(), the "reference" argument is an array of null MetadataReference and it crash.
Based on what I read, I think (but I'm not sure) that Roslyn can't work on android because of the missing location of System.Object.
So can someone can confirm (or invalidate) if there is a way to work with Roslyn on Android ?
(Bonus point if you know some other way to compile/execute or "interpret" C# code on any device)
Thank for reading and stay safe.
I am trying to modify a class that I have obtained from an open source library. While I have referenced the library in my project, the original class contained references to parts of the library that are marked internal. This is causing build errors in my code.
I read this answer: How do you "override" an Internal Class in C#?. Note that it indicates that one is out of luck when wanting to access an internal class when one does not have access to the source code. This is, however, not the case for me.
I can fix this, but I want to know if there is a good way to do it. It appears to me that I have two options. I could modify the source code for the internal class so that it is not internal (bad), or I could import the class itself directly into my project (worse). If I import the class, there are further reference issues, and I will probably have to import the entire library to fix the dependencies.
Note that I am aware that I could add my change to the open source library and then build it as new library to reference in my code. I do not want to do this at this time because I would like to be able to step into my method in the debugger. Once I have debugged my method and assured its utility, I will make it available as part of my version of the open source project.
I am new to c# and this is my first time working on a large open source project so I would like some advise on how to deal with this issue.
Update:
Here is the link to the source code of the library that I would like to modify: https://github.com/accord-net/framework/blob/development/Sources/Accord.Math/Optimization/Unconstrained/Least%20Squares/LevenbergMarquardt.cs
To modify this code, I opened the source in visual studio and attempted to build the version as it currently exists. On line 304 the following code appears:
int[] block = Vector.Range(s * blockSize, s * blockSize + B);.
When I have this file in visual studio, it gives me an error saying that Vector is inaccessible due to its protection level. When I look at the definition of that code in the intellisense window, it shows that Vector is marked as internal.
If I attempt to bring the source code of Vector into my project, there are even more issued of the same type because Vector uses other internal classes.
Library version:
Are you sure that you're using the latest version of the library ?
By looking at the source of Vector.Range I can see that it is a public member.
Nuget packages of Accord.NET seems up to date, so check out your current version.
Additionally, I would recommend you to depend on the NuGet package instead of a manually installed assembly (you would see update notifications in Nuget Package Manager as a bonus).
Extending the library:
You have a couple of options here,
discuss with the authors about the possibility of opening some internal types, explain your needs and they might even suggest an alternative path without making such changes on their side
fork the library and make your changes, eventually PR
(personally I'd try step 1 first)
Debugging:
When referencing the Nuget package, you can create a PDB out assembly references using Telerik JustDecompile (freeware). Doing so relieves you to drag your own build and so on.
i have seen in the link below:
Can execute Code Dynamically in monotouch?
that it is impossible to use dynamic in ios xamarin. how about in Andoid xamarin?
I tried to do the following:
dynamic MyDynamic = new System.Dynamic.ExpandoObject();
MyDynamic.A = "A";
MyDynamic.B = "B";
However, when I want to access MyDinamic.A, it says that Unknown Member: A.
Can someone please help? Thanks.
Edit:I also have added the Microsoft.Csharp dll in the solution reference as per the screenshot:
I'm not sure which IDE did you use for developing your xamarin android app, by my side I used VS2015, and the error is
Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'
This is because when use the dynamic keyword in your project. The assembly contains the C# runtime binder. To solve this issue, we need to add reference to Microsoft.CSharp library(Microsoft.CSharp.dll) in our project:
After adding this reference, your code runs well by my side.
But I'm not sure if the Xamarin.Android will limit the use of dynamic object, through I didn't find any limitation in xamarin's official document. For more information about dynamic object, you can refer to:
System.Dynamic.DynamicObject Class
System.Dynamic.ExpandoObject Class
Go to NuGet Package Manager > Manage NuGet packages menu. Then change Source to Microsoft Visual Studio Offline Packages. After adding, it should compile successfully.
I'm getting the following error:
error CS1704: An assembly with the same simple name
'Interop.xxx.dll, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null has already been imported. Try removing one of the
references or sign them to enable side-by-side.
Everything I've seen says that I am referencing two assemblies with the same name and I need to remove one of them. However, I've checked and I'm only referencing it once.
This also only happens when I'm using msbuild to build from the command line on my dev box. If I build through Visual Studio or do a clean build on our CI server I don't see this error.
I've tried completely removing all of my source and building from scratch to more closely resemble the build machine but no luck.
So it looks like I can't read today!
The project had a reference to the Interop and a COM reference that generated the "same" interop. So there were two and I just didn't search very well. I still don't understand why it worked in other places but this did fix it.
In the Error List window, the project that was triggering this error was listed in the Project column. I got around the error by doing the following:
I unloaded the listed project (right-click => Unload Project)
Opened the XML for edit (right-click the unloaded project => Edit {ProjectName.csproj}).
Searched for the offending .dll, and noticed it was listed multiple times in the XML
Removed the entire Reference tag related to the offending dll, and did so for every copy of the reference except the first one listed
The reason it was listed multiple times was because several referenced libraries used that dll. This shouldn't be a problem, in and of itself, so I'm not sure what caused this error to suddenly pop up for me. I'll update this answer if I figure that out.
In my case the duplicate entry was caused by a NuGet package reference and a direct file reference to the same assembly in the packages folder. I am not sure how the project got into this state, but unloading the project and searching the XML file for the offending assembly name resolved the issue for me.
Note that in my case this started happening after updating a NuGet package to a newer version with no other changes to the project, so this maybe caused by a bug in NuGet.
If this is a web project, are there any strong-named references to the other version there? Those won't show up as a project dependency, but will cause a run-time error like you describe. Hope that helps
I had this problem but in my case, I had an old copy placed in the current folder for the EXE loading my component, that was loaded together with the current one, that was loaded by hand from my projects folder. Deleting that old copy solved my problem.
I used Debug > Windows > Modules window to see which modules were loaded at that time and that solved my problem.
For others facing the same as me: if building via command line using property AssemblyName, it will overwrite all assemblies generated by all solution projects - in other words, you will end up with (N -1) assemblies named the same where N is the no. of projects - the startup one (which generally will generate an exe).
This happens because all build command line properties are global and overwrite any project-specific setting. See this and this.
From the msdn link mentioned above:
Global properties are properties that are set by using the
/property switch on the command line, or properties that are set by
the integrated development environment (IDE) before a project is
built. These global properties are applied to all projects that are
built by using this Engine.
In my specific case, where Jenkins is the CI tool, I ended up adding a windows batch command at the end to rename the .exe only to what I originally intended when passing the AssemblyName parameter.
For those developing UWP projects that have project references that include specifically the Microsoft.Windows.SDK.Contracts nuget package (or other dependencies that reference it), this is a common error when the version of the SDK contracts is targeting a different version of the runtime to how your project is configured.
For instance, when targeting Windows 10, version 1903:
Any dependencies or reference projects should target or at least support the same runtime version.
it is common thought process to update all NuGet packages when a new stable version is available, but this is not always a helpful practise on its own. Just because a new stable version of a package is available does not mean that you should or that you can easily use that version.
Even though this package for SDK contracts has a stable update, it is not compatible with my main project configuration, Nuget does not know this so it allows the update.
This package is specifically designed to provide windows dlls for project types that DO NOT have windows platform targeting support, it copies the same dlls that are included by the UWP targeting config. By installing later versions of the package the references from the satellite project will be included in the output along with those provided due to platform targeting, ultimately causing OPs error.
There are similar SDK and targeting packs for Windows IoT Device Runtimes, this information should help you identify and resolve those issues if you get stuck on this issue as my team often does :)
In my case, the issue was on wrong characters in the ProjectReference section of my csproj file.
Background
I have a project that references another library I maintain, which I publish as a NuGet package.
Whenever I make changes to my library, I usually reference the local dll in my project to test and make sure everything looks good before I publish the library as a NuGet package.
When testing, I just comment out the PackageReference line and uncomment the ProjectReference one so it references my local dll, like so:
<ProjectReference Include="..\..\my-class-library\MyClassLibrary.csproj" />
<!--<PackageReference="MyClassLibrary" Version="2.0.1"/>-->
Root cause
I had the slashes inverted, so I was using / rather than \ in the path, like so:
<ProjectReference Include="../../my-class-library/MyClassLibrary.csproj" />
Once corrected, the issue went away.
Try this instead: remove Interop.xx.dll from the reference section in Solution Explorer and Rebuild the project
In our case this error was shown when we had a duplicate reference inside the .csproj file (although I have no idea how this happened).
The difference to an already posted answer is that, in our case, one was a project reference and another one was direct binary reference to a dll.
Once we removed one of those, project correctly compiled.