jaredpar / basic-reference-assemblies Goto Github PK
View Code? Open in Web Editor NEWProduce NuPkg files that have .NET Reference assemblies as resources
License: MIT License
Produce NuPkg files that have .NET Reference assemblies as resources
License: MIT License
The ReferencInfo
type is in the generic Basic.Reference.Assemblies.Net70
namespace. That means when a project references two different TFM specific versions of the NuPkg the type name clashes. This needs to be under the Net70
type or a namespace.
Think it's probably more composable to put most types into a namespace vs. the current sub-type setting.
Why System.Text.Json.dll
reference assembly is not provided by this library? Is not it "basic" enough ?
Hello!
First of, thank you for creating this awesome package. It solved some major headaches for me.
May I suggest an improvement to WithReferenceAssembleis extension method?
Currently, it is implemented as compilation.WithReferences(...)
which replaces everything one might have provided during compilation creation. Would it be better to replace it with compilation.AddReferences()
which does preserve the existing references?
If the idea sounds good, I can submit a PR to the effect.
I can run your snippet inside a console app in .net core 7 but changing the framework to .net standard 2.0 crash with :
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.CodeAnalysis.CSharp, Version=4.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified
I'm using Visual Studio 17.5.0 Preview 2.0 with C# Tools 4.5.0-xxx and building an incremental source generator.
I think I need an unreleased Microsoft.CodeAnalysis.CSharp, Version=4.5.0.0?
https://www.damirscorner.com/blog/posts/20221014-VersionsOfSourceGeneratorDependencies.html
Hey @jaredpar, I'm looking in your project with much interest.
Could it be considered to add the windows specific reference assemblies? In a specific package?
I'm talking about theses ones:
The framework specific packages are great for trimming down deployment size, but unfortunately the package dependencies undermine this by pulling the overly general Microsoft.CodeAnalysis
package, which pulls in both VB and C# analysers and other unnecessary dependencies.
Replacing this with Microsoft.CodeAnalysis.Common
will make this package more compatible with applications doing runtime code generation focusing only on specific languages, such as C#, which means they will be pulling only Microsoft.CodeAnalysis.CSharp
package as a dependency.
Name speaks for itself, I would like to use this library to add references to asp.net related packages into my inmemory compilation. These would be the contents of https://www.nuget.org/packages/Microsoft.AspNetCore.App.Ref
Hi,
I am trying to add runtime compilation to a project but am struggling a bit with setting up the references to the framework assemblies.
My code currently looks like this:
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis.CSharp;
namespace DynamicCompilationWithWpf
{
class Program
{
static void Main(string[] args)
{
string sourceCode = @"
public class TestClass
{
public System.Windows.Point DummyMethod(System.Windows.Point p1)
{
return new System.Windows.Point(p1.Y, p1.X);
}
}
";
var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode);
var references = new List<Microsoft.CodeAnalysis.MetadataReference>(Net50.All);
//references.Add(Microsoft.CodeAnalysis.MetadataReference.CreateFromFile(@"C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\5.0.0\ref\net5.0\WindowsBase.dll"));
var options = new CSharpCompilationOptions(Microsoft.CodeAnalysis.OutputKind.DynamicallyLinkedLibrary)
.WithPlatform(Microsoft.CodeAnalysis.Platform.X64)
.WithOptimizationLevel(Microsoft.CodeAnalysis.OptimizationLevel.Release);
var compilation = CSharpCompilation
.Create(
null,
new[] { syntaxTree },
references: references,
options: options);
var stream = new MemoryStream();
var emitResults = compilation.Emit(stream);
if (!emitResults.Success)
throw new Exception();
Assembly dynamicAssembly = Assembly.Load(stream.ToArray());
dynamic instance = dynamicAssembly.CreateInstance("TestClass");
System.Windows.Point result = instance.DummyMethod(new System.Windows.Point(3, -1));
}
}
}
Here the project file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Basic.Reference.Assemblies.Net50" Version="1.2.4" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="3.11.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.11.0" />
</ItemGroup>
</Project>
The error is 'Type System.Windows.Point or namespace cannot be found ...'.
I can verify that the containing assembly (WindowsBase) is in the list created by Net50.All.
When manually adding a reference to the list, the error disappears and the compilation succeeds.
Am I missing something here?
Would it be possible to publish an updated NuGet package with the changes from #11 ?
Hello Jared,
First I just want to say thank you for creating this project. It has been a big help!
I have a couple of non-framework assemblies that my scripts use. Would it be better to create reference assemblies for them and use those during compilation, instead of the actual implementation assemblies?
Thanks,
-Jake
Hello!
I'm using net5, and I'm trying to compile some c# code at runtime that depends on assemblies prebuilt from the cmd line with msbuild.
It works great, but I'm getting some warnings along the lines of:
warning CS1701: Assuming assembly reference 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' used by 'Sharpmake.CustomPlugin' matches identity 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' of 'System.Runtime', you may need to supply runtime policy
I'm not very familiar with the net5 toolchain intricacies yet, but I noticed that in C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\5.0.0\data
there's a PackageOverrides.txt
that indicates some version overrides, like System.Runtime|4.3.0
.
Could that be related? And should those overrides be handled by basic-reference-assemblies?
Apologies if it's out of the scope of this repo.
Thanks!
I have a project which uses ReferenceAssemblyKind.Net50
.
In the current version it was removed (e.g. to remove the binary size...) - how should users query for net5.0?
Hello. Thanks for this - it looks very promising and I hoped it would save me after hours of failure today... but when I copy the code from your readme verbatim (except for adding a System.IO using statement and changing the drive from p:\ to C:), I get this:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
Any ideas what could be causing this? Am I doing something wrong or is there a bug/omission in the library? I'm on Windows 10. I created a standard .net 5.0 console app, added using statements, and pasted your code in the Main method.
Hello. I am using DependencyContext .Default .CompileLibraries
to get references. which namespace in Microsoft.Extensions.DependencyModel
.
It works(However, there are some fields or attributes whose metadata cannot be found during dynamic compilation).
What is the difference between Microsoft.Extensions.DependencyModel
and basic-reference-assemblies?
Today, the various properties on References
are declared as get-only properties with an initialiser. Example:
public static PortableExecutableReference Accessibility { get; } = AssemblyMetadata.CreateFromImage(Resources.Accessibility).GetReference(filePath: "Accessibility.dll", display: "Accessibility (net472)");
There's also a static All
property which stores all of the other PortableExecutableReference
s in an array.
All of these initialisers always run (when the References
class is first accessed), so all of the embedded resources are always loaded, even if you only need to use one of them. It looks like the resources total around 50MB (which is retained until the process terminates, since they are static fields), but also on the Desktop Framework there's additional garbage generated by the stream.CopyTo
call in GetResourceBlob
.
Would you be open to loading the resources lazily so that we only pay for what we use?
private static PortableExecutableReference? _accessibility;
public static PortableExecutableReference Accessibility
{
get
{
if (_accessibility == null)
{
_accessibility = AssemblyMetadata.CreateFromImage(Resources.Accessibility).GetReference(filePath: "Accessibility.dll", display: "Accessibility (net472)");
}
return _accessibility;
}
}
This could be changed to use System.Lazy
if you want to be certain to load the resource once only (thread safety). Would you accept a pull request containing a change like this?
I have a project where I'm using Basic.Reference.Assemblies.Net70 1.4.2, that uses Microsoft.CodeAnalysis.CSharp to compile some on the fly created classes. After updating it to 1.4.4, I'm starting to get the following error:
System.InvalidOperationException: Resource 'net70.System.Reflection.Metadata' not found in Basic.Reference.Assemblies.Net70, Version=1.0.0.0, Culture=neutral, PublicKeyToken=00aeae93c2ffe759.
at Basic.Reference.Assemblies.ResourceLoader.GetResourceStream(String name) in /home/runner/work/basic-reference-assemblies/basic-reference-assemblies/Shared/ResourceLoader.cs:line 17
at Basic.Reference.Assemblies.ResourceLoader.GetResourceBlob(String name) in /home/runner/work/basic-reference-assemblies/basic-reference-assemblies/Shared/ResourceLoader.cs:line 25
at Basic.Reference.Assemblies.Net70.References.get_SystemReflectionMetadata() in /home/runner/work/basic-reference-assemblies/basic-reference-assemblies/Basic.Reference.Assemblies.Net70/Generated.cs:line 1911
at Basic.Reference.Assemblies.Net70.References.get_All() in /home/runner/work/basic-reference-assemblies/basic-reference-assemblies/Basic.Reference.Assemblies.Net70/Generated.cs:line 2821
at ....
The method where that error is thrown looks like the following:
var references = new List<MetadataReference>(Net70.References.All)
{
MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location)
};
Reverting back to 1.4.2 solves the problem. Not sure what was changed between 1.4.2 and 1.4.4, but something broke.
Generate for net70
Will there be an update that targets the final .NET 8 release in the near future?
As the set of references and use cases have increased I'm finding the existing code structure hard to deal with. Specifically:
ReferenceInfo
is a type that is per assembly so it's impossible to share logic across target frameworksNet60
types is leading to a lot of name ambiguities.ReferenceInfo
types to be inside a type named References
and References
to not be in a typeAs such I'm changing the code structure as follows:
Deconstruct
and AsTuple
method to ReferenceInfo
that will return a value that can be shared amongst all the assembliesReferences
to ReferenceInfos
References
These changes will be reflected in the 1.4 release series.
Hello!
This csproj file is referencing an older preview version (6.0.0-preview.7.21377.19) of the Microsoft.NETCore.App.Ref instead of the latest stable version (6.0.5).
https://www.nuget.org/packages/Microsoft.NETCore.App.Ref/6.0.5
Is that any particular reason that an older version is used? Or the version number does not matter in this case?
Heya!
I was trying to move from the base package to the Basic.Reference.Assemblies.Net50 one, and had to change my code from using Basic.Reference.Assemblies.ReferenceAssemblies.Net50
to Basic.Reference.Assemblies.Net50.All
.
It's not a big deal, but would be nice to either add the alias or change the readme to document that in the https://github.com/jaredpar/basic-reference-assemblies#what-if-i-only-need-a-single-target-framework section.
Thanks!
As mentioned in the new documentation for persistable dynamic assemblies in .NET 9 here, to create assemblies for specific TFMs (or assemblies that can actually be used as references in modern C# projects), the new API requires you to create a MetadataLoadContext using the reference assemblies for that TFM. As is already noted by this package's README, this can be challenging!
Adding a bit of documentation that myself and others can point to (or even a helper method to create a MetadataLoadContext like exists for Compilations) would help a lot (I am completely willing to contribute this myself).
This also currently always pulls in a dependency for Microsoft.CodeAnalysis.Common, which if you just want the embedded resources for the assembly files (for example to use for this, or other applications like loading them with AsmResolver.DotNet or MetadataReader) can cause a fairly large transitive dependency that isn't wanted. I completely understand if this is out of scope for what you have here, just let me know if that's the case, I'll probably end up creating a fork of what you have as a separate package.
When this project first started there were only a few Target Frameworks so having Basic.Reference.Assemblies.nupkg
contain all of them was reasonable. Now though the number of target frameworks has increased significantly and having them all included is getting a bit unweildy. Mostly because the package size is getting to big to be reasonably used.
Going forward going to fix this by doing the following:
netstandard1.3
it will still be there, just as a stand alone packageBasic.Reference.Assemblies
netstandard2.0
net472
which represents the most prevalent .NET Framework targetA declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.