Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

.NET dependencies resolving not working as expected #435

Open
KirillBorunov opened this issue Nov 1, 2023 · 3 comments
Open

.NET dependencies resolving not working as expected #435

KirillBorunov opened this issue Nov 1, 2023 · 3 comments

Comments

@KirillBorunov
Copy link
Contributor

KirillBorunov commented Nov 1, 2023

Hi, seems there is a problem with dependency resolving when the application is run by SampSharp vs when is run directly.
The test case is with the nuget package System.Text.Json.
If I try to use it running the server then I get an exception (details below), but if I run the program as console application then it works ok.

Exception:

System.IO.FileLoadException: 'Could not load file or assembly 'System.Text.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The located assembly's manifest definition does not match the assembly reference. (0x80131040)'

Seems to be related to the library with the same name included in the .NET Core but it happens only with SampSharp.
I tested only on Windows.

NuGet package: System.Text.Json 7.0.3

Test code:

public static void Main(string[] args)
{
    System.Text.Json.JsonSerializer.Deserialize("{}", typeof(object));

    new GameModeBuilder()
        .Use<GameMode>()
        .Run();
}

• If I run as server without NuGet package: loaded correct version from SERVER_FOLDER\dotnet\shared\Microsoft.NETCore.App\6.0.7\System.Text.Json.dll
• If I run as console app without NuGet package: loaded correct version from C:\Program Files (x86)\dotnet\shared\Microsoft.NETCore.App\6.0.24\System.Text.Json.dll
• If I run as console app with NuGet package: loaded correct version from SERVER_FOLDER\gamemode\Debug\net6.0\System.Text.Json.dll
• If I run as server with NuGet package: EXCEPTION!

What I tried:
copy System.Text.Json.dll to SERVER_FOLDER: EXCEPTION!
copy System.Text.Json.dll to SERVER_FOLDER\dotnet\shared\Microsoft.NETCore.App\6.0.7: WORKED!

Tried another package with no name conflict Newtonsoft.Json 13.0.3 and it works ok in all cases.

Seems when running SampSharp, it is trying to resolve the assemblies in wrong order paths, it seems that is checking the .NET libraries folders first.

@KirillBorunov
Copy link
Contributor Author

I got a workaround. It needs more tests and checks, maybe can cause other problems. But for now seems to work good.

private static void ApplyAssemblyResolveFix(string searchDirectory)
{
    AppDomain.CurrentDomain.AssemblyResolve += (object? sender, ResolveEventArgs args) =>
    {
        Debug.WriteLine($"Resolving assembly: {args.Name}");

        var assemblyName = new AssemblyName(args.Name).Name;
        var resolvedPath = Path.Combine(searchDirectory, $"{assemblyName}.dll");

        if (File.Exists(resolvedPath))
        {
            Debug.WriteLine($"Resolved path: {resolvedPath}");
            return Assembly.LoadFile(resolvedPath);
        }

        Debug.WriteLine("Not resolved.");
        return null;
    };
}

Usage:

public static void Main(string[] args)
{
	var appDirPath = GetApplicationLocation();
	
	ApplyAssemblyResolveFix(appDirPath);

	//Use the library...

	new GameModeBuilder()
		.Use<GameMode>()
		.Run();
}

private static string GetApplicationLocation()
{
	var entryAssembly = Assembly.GetEntryAssembly() ?? throw new InvalidOperationException("Unable to determine the entry assembly.");
	var appDirPath = Path.GetDirectoryName(entryAssembly.Location);
	if (string.IsNullOrEmpty(appDirPath))
	{
		throw new InvalidOperationException("Unable to determine the application's location.");
	}
	return appDirPath;
}

@ikkentim
Copy link
Owner

ikkentim commented Feb 5, 2024

Check your package references. The versions in the package references for MS packages (eg. Microsoft.Extensions.XYZ) should match the version of the runtime you're using (in this case 6.x.x)

@KirillBorunov
Copy link
Contributor Author

Check your package references. The versions in the package references for MS packages (eg. Microsoft.Extensions.XYZ) should match the version of the runtime you're using (in this case 6.x.x)

That seems to be a common mistake. Package version and target framework version seems to be independent.
Please consider these arguments:

  1. In the package versioning documentation never mentions nothing about package version and target framework "entanglement": https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/versioning
    I cannot find any info from MS where it says we should use the same package versions as the runtime. I think it just a Microsoft convention to use the packages versions same as framework version because these libraries comes with the framework, but you can get a newer version from the Nuget and it should work as any other package.

  2. If there were a "version entanglement", so why the packages includes the target frameworks? There is no need for it if we only need to match the versions with the framework...

  3. Example with System.Text.Json. Lets see the Nuget page: https://www.nuget.org/packages/System.Text.Json#supportedframeworks-body-tab
    At the moment of writing this, the package is at version 8.0.1, but supports .Net 6/7/8, .Net Standard2.0, .Net Framework 4.6.2. So I can use the version 8.0.1 of this package on any of these. In fact it works perfect without S# or with workaound (see my first post tests).

  4. Example with Newtonsoft.Json. Nuget page: https://www.nuget.org/packages/Newtonsoft.Json
    At the moment of writing, this package is at version 13.0.3. Do I need to wait .Net version 13 to use it? I think no, is just a package version, it supports .Net 6, .Net Standard 1/1.3/2, .Net framework 2/3.5/4/4.5 and it will work with any of these.

  5. Without S# it works.

  6. With my workaround it works.

@ikkentim ikkentim closed this as completed Feb 6, 2024
@ikkentim ikkentim reopened this Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants