Laden...

Kompatibilität .NET Standard zu .NET Framework

Letzter Beitrag vor 5 Jahren 11 Posts 3.024 Views
Kompatibilität .NET Standard zu .NET Framework

Hallo

Ich bin sicher nicht der erste mit dem Problem, aber mit der Suche habe ich nichts gefunden.

Problem:
Wir haben eine SOA Architektur, basierend auf ASP.NET Web API (.NET Framework).

Nun startet parallel ein zweites Projekt, welches unsere Basis-Funktionalität verwenden möchte. Dieses Projekt startet mit .NET Core. Da wir nicht 'mal schnell' auf Core gehen können und die anderen natürlich nicht mehr mit .NET Framework starten wollen, habe ich unsere Basis-Funktionalität in .NET Standard überführt. Das funktioniert auch soweit.

Allerdings, habe ich nun das Problem, dass auf die STD Library aufsetzende .NET Framework Libraries Probleme mit der Typ-Kompatibiltät bekommen.

Konkreter Fall:

In der .NET Standard Library gibt es eine Klass mit folgendem Construktor:


    public sealed class RestConfigurationSource : BaseConfigurationSource
    {
//...
//HttpClient is from:
// Assembly netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
// C:\Program Files\dotnet\sdk\NuGetFallbackFolder\netstandard.library\2.0.3\build\netstandard2.0\ref\netstandard.dll
        internal RestConfigurationSource(HttpClient httpClient)
        {
//...

In einem darauf aufsetzendem Unit-Test Projekt (.NET Framework) versuche ich die Klasse zu initialisieren:


        internal static RestConfigurationSource CreateSource()
        {
            FakeHttpMessageHandler fakeResponseHandler = CreateFakeResponseHandler();
//HttpClient is from:
//System.Net.Http, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
//C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib\System.Net.Http.dll
            var client = new HttpClient(fakeResponseHandler);
//...
            var configSrc = new RestConfigurationSource(client);

Beim Versuch in die Methode zu springen bekomme ich folgende Exception:

Fehlermeldung:
System.MissingMethodException
HResult=0x80131513
Message=Method not found: 'Void MunichRe.Uwpf.Api.Core.Configuration.Rest.RestConfigurationSource..ctor(System.Net.Http.HttpClient)'.
Source=MunichRe.Uwpf.Api.Core.UnitTests
StackTrace:
...

Ist für mich erstmal nachvollziehbar. Die beiden Versionen von HttpClient entsprechen unterschiedlichen Klassen. Aber das muss ja ein Problem sein dass bei dem Arbeiten mit .NET Standard und .NET Framework bedacht wurde.

Könnt ihr mir vielleicht auf die Sprünge helfen, gerne einfach mit einem RTFM Link.

Danke schon Mal!
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

Also ich hab Schwierigkeiten, dein Verhalten bei mir nachzustellen.
Bei meinen Tests ist mir aber aufgefallen, dass eine Referenz scheinbar nicht gleich Referenz ist. Wenn ich bei der .NET Framework Assembly (UnitTest) die im Template voreingestellte Referenz auf die System.Net.Http.dll entferne und dann manuell im ReferenceManager suche und hinzufüge, ist das scheinbar eine andere Datei. Wenn parallel eine .NET Standard-Assembly referenziert ist, dann meckert er, dass es die HttpClient-Klasse doppelt gibt.

Hast Du Mal probiert, bei der .NET Framework Assembly alle "alten" Referenzen raus zu werfen und das Gegenstück von NuGet zu installieren?
Wenn ich auf beiden Seiten, .NET Standard und .NET Framework, nur mit dem NuGet-Package "System.Net.Http" arbeite, funktioniert alles.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

Hast Du Mal probiert, bei der .NET Framework Assembly alle "alten" Referenzen raus zu werfen und das Gegenstück von NuGet zu installieren?

Das ist der korrekte Weg.

Hallo Flo,

die Lösung wurde dir ja genannt, aber zum Hintergrund warum es so ist: vermutlich wurden die Bindingredirects* nicht korrekt generiert. Durch das Verwenden der NuGet-Pakete ist das hinfällig, da beide Seiten die gleiche Version verwenden. Hier hat dann wohl das Tooling irgendwie die Versionen nicht ausfinding machen können und daher keine Redirects generiert.

Schau dir dazu auch* Issues with .NET Standard 2.0 with .NET Framework & NuGet · Issue #481 · dotnet/standard

an.

* mMn ist dieses "Feature" ehere eine Notlösung, denn "hübsch" ist das alles nicht

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

Hallo Zusammen

Danke für eure Hilfe! Scheinbar hast das Verhalten speziell mit Unit Test (.NET Framework) Projekten zu tun.

Ich habe mittlerweile eine Test-Solution erstellen können in der das Verhalten dediziert nachvollziehbar ist.

.NET Standard DLL

using System.Net.Http;

namespace ClassLibrary1.STD {
    public class Class1Std {
        public Class1Std(HttpClient client) {
        }
    }
}

.NET Framework DLL (mit Referenz auf die Standard DLL)

using ClassLibrary1.STD;
using System.Net.Http;

namespace ClassLibrary1.Fx {
    public class Class1Fx : Class1Std {
        public Class1Fx(HttpClient client)
            : base(client) {
        }
    }
}

--> System.Net.Http ausgewechselt über NuGet

Unit Test Projekt (.NET Framework)

    [TestClass]
    public class UnitTest1 {
        [TestMethod]
        public void TestMethod1() {
            var c1 = CreateClass();
        }

        private Class1Fx CreateClass() {
            HttpClient client = new HttpClient();
            Class1Fx c1 = new Class1Fx(client);
            return c1;
        }
    }

--> Führt zu dem genannten Laufzeitfehlet

Console App (.NET Framework)

    class Program {
        static void Main(string[] args) {
            var c1 = CreateClass();
        }

        private static Class1Fx CreateClass() {
            HttpClient client = new HttpClient();
            Class1Fx c1 = new Class1Fx(client);
            return c1;
        }
    }

--> Funktioniert

Viele Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

Kannst Du das Test-Projekt zum Download anbieten?

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

Freilich. Ist angehängt.

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

Also ich kann den Fehler bei mir nicht nachstellen. Ich habe nichts geändert und alles baut anstandslos, auch wird alles ausgeführt.
Das Problem scheint also nicht an dem Framework zu liegen, sondern an deinem PC bzw. der lokalen Installation von NuGet oder irgendetwas Anderem.

Hast Du Mal die NuGet-Caches geleert?
Dazu gibt's in den Einstellungen unter NuGet einen Button.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

Kompilieren kann ich auch alles. Auch die Konsolen-Anwendung kann ich erfolgreich ausfhren. Kannst du den Unit Test ausführen? Hier bekomme ich den genannten Laufzeitfehler.

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

Auch ich kann die Solution problemlos laden, bauen - und testen; ohne Warning oder Error.
Die Wahrscheinlichkeit, dass es an Deinem Environment liegt, steigt und steigt.. 😉

Beim ersten Versuch nicht, da hat er gemeckert:

Fehlermeldung:
Der Testexecutor mit dem URI "executor://mstestadapter/v2" wurde nicht gefunden

Das konnte ich dann "beheben", indem ich das NuGet-Package "MSTest.TestAdapter" eine Version herunter gesetzt und dann wieder aktualisiert habe.
Das würde ich aber darauf schieben, dass ich das Package von dir ohne Cache bekommen habe, außerdem hab ich ein ähnliches Problem bei einem anderen Projekt - das liegt also nicht an deiner Test-Solution.

Danach lief der Test dann auch fehlerfrei durch, debuggen ließ er sich auch.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.