Adding MetadataReference in Roslyn Vs Microsoft.CodeAnalysis - c#

Roslyn version 1.2.* has a function called MetadataReference.CreateAssemblyReference() which takes the display name of the assembly and returns the appropriate MetadataReference object. For example I was able to add reference to various assemblies as follows:
Compilation compilation = Compilation.Create("HelloWorld")
.AddReferences(MetadataReference.CreateAssemblyReference("mscorlib"),
MetadataReference.CreateAssemblyReference("System.Linq"),
MetadataReference.CreateAssemblyReference("System.Data.Linq"),
MetadataReference.CreateAssemblyReference("System.Data"),
MetadataReference.CreateAssemblyReference("System.Data.DataSetExtensions"),
MetadataReference.CreateAssemblyReference("System.Xml"),
MetadataReference.CreateAssemblyReference("System.Xml.Linq"),
MetadataReference.CreateAssemblyReference("System"),
MetadataReference.CreateAssemblyReference("System.Core")
//MetadataReference.CreateAssemblyReference("System.Core"),
/*MetadataReference.CreateAssemblyReference("System")*/)
.AddSyntaxTrees(tree);
This however does not seem possible with the Microsoft.CodeAnalysis package (this is the latest package that one can install from Nuget). This package has a few functions inside MetadataReference - but they either require an Assembly or a file path.
Does that above mentioned simpler function exist in newer compiler packages?

You can load the assembly with the CLR loader and find out where it was loaded from:
typeof(DataSetExtensions).Assembly.Location

Related

How does csc/Roslyn resolve assembly version?

I have a console program that has two direct dependencies: ClosedXML v0.97 and ClosedXML.Report 0.2.4. The ClosedXML.Report dependency also depends on ClosedXML, but in a version 0.95.
When I try to compile the program in NET6 (basically only a reference to a class in the ClosedXml.Report),
_ = new XLTemplate(new System.IO.MemoryStream());
I get a compiler error
CS0012 The type 'IXLWorkbook' is defined in an assembly that is not referenced. You must add a reference to assembly 'ClosedXML, Version=0.95.0.0, Culture=neutral, PublicKeyToken=null'.
Why doesn't csc.exe recognize the 0.97 version to use and requests 0.95 (the indirect dependency)? The assembly version of package is same as the nuget version.
Nuget uses direct-dependency-wins mechanism and I though .net core also uses that for assemlby resolution. Is a mechanism different? How does roslyn resolve which version to use and when to throw an error?
Relevant piece of MSBuild
C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\Roslyn\csc.exe
/reference:C:\Users\username\.nuget\packages\closedxml\0.97.0\lib\netstandard2.0\ClosedXML.dll
/reference:C:\Users\username\.nuget\packages\closedxml.report\0.2.4\lib\netstandard2.0\ClosedXML.Report.dll
One possible explanation for this behavior would be if IXLWorkbook, which is apparently required by the call to new XLTemplate() no longer exists in Version 0.97 of ClosedXML.
If possible, try to rebuild ClosedXML.Report with ClosedXML 0.97. Since these apparently are early versions (Version < 1.0) breaking changes between versions seem possible. Also, can you make sure that the output bin directory actually contains Version 0.97?

Fixing "They type 'X' exists in both 'Y' and 'Z'" C# error for System.ServiceModel in LINQPad

If I:
Create a new C# query in LINQPad 6.
Add the System.ServiceModel.Http NuGet package or another package that references it.
Try to instantiate a class from the System.ServiceModel namespace, for example System.ServiceModel.BasicHttpBinding.
Leading to the following .linq file:
<Query Kind="Expression">
<NuGetReference>System.ServiceModel.Http</NuGetReference>
</Query>
new System.ServiceModel.BasicHttpBinding()
Then I get a compile error:
CS0433 The type 'BasicHttpBinding' exists in both 'System.Private.ServiceModel, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'System.ServiceModel.Http, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
If I create a project in Visual Studio and add the same NuGet package and code, I do not get this error.
According to the C# Language reference for the error, it should be possible to resolve by using the -reference compiler option or by not referencing one of the assemblies. However, I can't seem to find a way to use this compiler option in LINQPad, nor can I find any way to remove the assembly reference to System.Private.ServiceModel.
How can I fix the error?
This is a bug in LINQPad, triggered by an obscure scenario. The System.Private.ServiceModel package contains a lib folder with an assembly which is required at runtime, and a ref folder with a underscore.underscore file which indicates that no assemblies should be referenced by the compiler. Because LINQPad finds no reference assemblies, it feeds the compiler the assembly in the lib folder, which causes the error.
I've got a fix ready and regression tests are currently running. The fix will likely make it into the 6.11.2 beta build, which should be released in a day or two.

In my .Net Standard Library project, System.Configuration.ConfigurationManager does not seem to work

In my .Net Standard Library Project,
System.Configuration.ConfigurationManager does not seem to work.
Even the method Does not get called, which contains the Statement
object o = ConfigurationManager.GetSection(_strSectionName);
I have Installed the Nuget package
System.Configuration.ConfigurationManager version 4.6.0
But if I right click on ConfigurationManager in this statement,
object o = ConfigurationManager.GetSection(_strSectionName);
It shows me the metadata of version 4.0.2.0, namely
Assembly System.Configuration.ConfigurationManager, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
where I think the version it should go to is 4.6.0.
Maybe that is causing the problem.
The assembly version is correct, it should be 4.0.2.0, this is separate from the package version (here 4.6.0).
This is not the cause of your problem. The next thing to look at is the exception, or the incorrect behaviour.

Why do I receive a warning about an assembly reference that appears to be identical in version and culture

I am using Xamarin on a Mac and have built up a series of .netstandard1.3 libraries. One of which is referencing a few external packages:
NETStandard.Library
Newtonsoft.Json
System.Linq.Queryable
System.Reactive
System.Security.Principal
When I build the project (library) it builds but with the following warning:
/Library/Frameworks/Mono.framework/Versions/4.8.1/lib/mono/xbuild/14.0/bin/Microsoft.CSharp.targets (CoreCompile target) ->
CSC: warning CS1702: Assuming assembly reference
System.Runtime.Serialization.Primitives, Version=4.1.1.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' matches assembly
System.Runtime.Serialization.Primitives, Version=4.1.1.0,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
You may need to supply runtime policy
I'm not directly referencing this specific library anywhere, but even if I were the version and public key token appear to be identical so why the complaint? How do I get rid of this warning and why am I getting it?
Despite having the same assembly identity, there are different implementations of System.Runtime.Serialization.Primitives.dll presumably because of runtime specific behavior / implementation. MSBuild is not sure which to use. You may target your library to multiple runtimes, or distribute it as a NuGet package which shifts the responsibility of picking a target runtime to the library or app consuming your package. You can download the package, change it to a .zip and take a peak inside to see what I mean.

Can't get ILMerge to build single-file console application that works

I'm trying to create a single-file executable. The code is .Net-based and also relies on some additional libraries including SQLite.
When I compile the source code, all of the relevant files go into the Release directory, although the SQLite DLL (sqlite3.dll) goes into a sub-directory (x86). I think this happens because I'm using SQLite-raw and that "spits out" both x86 and x64 copies of the DLL.
My initial command line to try is:
ILMerge /out:GEDtoRH.all.exe GEDtoRH.exe *.dll /target:exe /targetplatform:"v4,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2" /wildcards /log
This produces the following output that worries me:
AssemblyResolver: Assembly 'System.Runtime.WindowsRuntime' is referencing assembly 'System.Runtime'.
...
AssemblyResolver: Did not find assembly in framework directory.
AssemblyResolver: Unable to resolve reference. (It still might be found, e.g., in the GAC.)
AssemblyResolver: Assembly 'System.Runtime.WindowsRuntime' is referencing assembly 'System.Threading.Tasks'.
...
AssemblyResolver: Did not find assembly in framework directory.
AssemblyResolver: Unable to resolve reference. (It still might be found, e.g., in the GAC.)
AssemblyResolver: Assembly 'System.Runtime.WindowsRuntime' is referencing assembly 'System.IO'.
...
AssemblyResolver: Did not find assembly in framework directory.
AssemblyResolver: Unable to resolve reference. (It still might be found, e.g., in the GAC.)
Location for referenced module 'sqlite3' is ''
Should I be concerned about the unresolved references? The reason I ask is because the finished executable doesn't work. It breaks with a null reference exception (Object reference not set to an instance of an object) on this line:
file = await StorageFile.GetFileFromPathAsync(filename);
The un-merged version of the executable works fine :( It isn't "filename" that is broken as I've tried adding some extra tests and it is fine.
Try as I might to add the sqlite3.dll to the list of things to ingest, if I try, ILMerge just complains with a "Could not load assembly" error.
As SQLite is not a .NET library it doesn't contain any IL to be merged

Categories