webentwicklung-frage-antwort-db.com.de

Erweiterungsmethoden auflösen/LINQ-Mehrdeutigkeit

Ich schreibe ein Add-In für ReSharper 4. Dafür musste ich auf mehrere ReSharper-Assemblys verweisen. Eine der Assemblys (JetBrains.Platform.ReSharper.Util.dll) enthält einen System.Linq-Namespace mit einer Untergruppe von Erweiterungsmethoden, die bereits von System.Core bereitgestellt werden.

Wenn ich den Code bearbeite, entsteht eine Mehrdeutigkeit zwischen diesen Erweiterungen, sodass ich zum Beispiel nicht OrderBy verwenden kann. Wie könnte ich das lösen? Ich möchte die core LINQ -Erweiterungen verwenden und nicht die von ReSharper.

Beim Kompilieren wird folgende Fehlermeldung angezeigt:

Der Aufruf zwischen dem .__ ist mehrdeutig. folgende Methoden oder Eigenschaften: 'System.Linq.Enumerable.OrderBy<string,int>(System.Collections.Generic.IEnumerable<string>, System.Func<string,int>)' and 'System.Linq.Enumerable.OrderBy<string,int>(System.Collections.Generic.IEnumerable<string>, System.Func<string,int>)'

EDIT: Ich habe den folgenden Vorschlag ausprobiert, leider ohne Glück. In der Zwischenzeit habe ich das Problem "gelöst", indem ich die Verweise auf System.Core entferne. Auf diese Weise könnte ich die von ReSharper DLL Dateien bereitgestellten Erweiterungen verwenden.

Ich habe ein Beispielprogramm hochgeladen wo ich gerade die ReSharper DLL Dateien importiert habe, die ich brauchte. Ich habe den Alias ​​von System.Core in SystemCore geändert, die extern alias-Direktive hinzugefügt, aber es hat immer noch nicht funktioniert. Wenn ich etwas verpasst habe, lass es mich wissen . P.S. Die Verweise beziehen sich auf ReSharper v4.1 DLL Dateien, die im Standardverzeichnis von "C:\Program Files\JetBrains\ReSharper\v4.1\..." installiert sind.

27
Igal Tabachnik

Dies ist kein Problem mehr, da ich die LINQ-Erweiterungen verwenden kann, die von ReSharper DLL -Dateien bereitgestellt werden, selbst wenn .NET 3.0 als Ziel ausgewählt wird.

Herr Skeet hatte wieder recht! Ich kann die vollständige LINQ-Syntax verwenden, während ich in den Eigenschaften des Projekts auf .NET 3.0 ausgerichtet bin und nicht auf System.Core!

2
Igal Tabachnik

Dies ist wahrscheinlich einer der seltenen Fälle, in denen die Verwendung eines externen Alias ​​ sinnvoll ist.

Ändern Sie auf der Eigenschaftenseite für den Verweis auf System.Core (dh wählen Sie unter Verweise System.Core, klicken Sie mit der rechten Maustaste und wählen Sie "Eigenschaften"), und ändern Sie den Wert für "Aliases" in "global, SystemCore" (oder nur "SystemCore", falls Zum Anfang ist es leer.

Dann schreiben Sie in Ihren Code:

extern alias SystemCore;
using SystemCore::System.Linq;

Dadurch werden alle relevanten Typen usw. im System.Linq-Namespace von System.Core.dll verfügbar. Der Name "SystemCore" ist hier beliebig - Sie könnten es "DotNet" oder etwas anderes nennen, wenn dies für Sie klarer wäre.

41
Jon Skeet

Dies ist nicht wirklich eine Antwort, bietet aber möglicherweise eine einfachere Möglichkeit, das Problem zu reproduzieren (von der Befehlszeile aus - Sie können dies mit zwei Projekten in Visual Studio tun, wenn Sie möchten).

1) Erstellen Sie BadLinq.cs und erstellen Sie es als BadLinq.dll:

using System.Collections.Generic;

namespace System.Linq
{
    public static class Enumerable
    {
        public static IEnumerable<T> Where<T>(this IEnumerable<T> source, 
                                              Func<T,bool> predicate)
        {
            return null;
        }
    }
}

2) Erstellen Sie Test.cs:

extern alias SystemCore;

using System;
using SystemCore::System.Linq;

static class Test
{
    static void Main()
    {
        var names = new[] { "Larry", "Curly", "Moe" };

        var result = names.Where(x => x.Length > 1);
    }
}

3) Kompilieren Sie Test.cs und geben Sie dabei den externen Alias ​​an:

csc Test.cs /r:BadLinq.dll /r:SystemCore=System.Core.dll

Das scheitert bei:

Test.cs (11,28): Fehler CS1061: 'System.Array' enthält kein Definition für 'Wo' und Nein Erweiterungsmethode 'Where' akzeptiert ein erstes Argument vom Typ 'System.Array' konnte gefunden werden (fehlt eine using-Direktive oder eine Assemblyreferenz?)

Wenn Sie es so ändern, dass keine Erweiterungsmethode verwendet wird (d. H. Enumerable.Where), funktioniert es problemlos mit dem externen Alias.

Ich denke das kann ein Compiler-Fehler sein. Ich habe eine private Mailingliste per E-Mail verschickt, die das C # -Team liest. Ich werde diese Antwort aktualisieren oder eine neue hinzufügen, wenn ich zurückkomme.

6
Jon Skeet

Damit ReSharper mit der Vielzahl der verwendeten Lösungen so gut wie möglich kompatibel ist, wurde es mit .NET 2.0 entwickelt. LINQ usw. wurde in C # 3.0 eingeführt, daher sind sie in dieser Version des Frameworks nicht verfügbar. Also, JetBrains hinzugefügt in ihrer eigenen Version.

Die Lösung besteht darin, Ihr Add-In auch gegen .NET 2.0 zu erstellen.

2
Nick Chadwick

Ich hatte ein mehrdeutiges Referenzproblem bei der Verwendung von System.ComponentModel. Visual Studio beschwerte sich, dass eine DLL -Datei in Version 2 und Version 4 vorhanden ist. Ich konnte es beheben, indem ich den Verweis auf die Datei System DLL entfernte und es las.

1
Ujain

Bei der Verwendung von PagedList in MVC (.Net 4.5, MVC 5) habe ich diese Art von Mehrdeutigkeit festgestellt. Ich stellte fest, dass das Problem gelöst wurde, wenn ich das Objekt für das mehrdeutige Argument annahm und es zuerst explizit formulierte. Wenn die Mehrdeutigkeit zwischen einer Methode, die System.Linq.Enumerable verwendet, und einer Methode, die System.Collections.Generic.IEnumerable als fraglichen Parameter verwendet, und der Quelle den Typ System.Collections.Generic.IEnumerable hat, tue ich nicht Verwenden Sie die Erweiterungsmethode. Ich besetze es. In diesem Beispiel gibt meine Repository-Methode eine Liste zurück:

searchRequest.CaseSearchResults = csr.SelectMatchingCases(searchRequest);
var results = searchRequest.CaseSearchResults.AsEnumerable<CaseSearchResult>();
int pageNum = (int)(ViewBag.PageNum ?? 1);
var pageResults =results.ToPagedList<CaseSearchResult>(pageNum, 5);

Das Aufrufen der Erweiterungsmethode unter searchRequest.CaseSearchResults hat den Mehrdeutigkeitsfehler verursacht. explizit auf Ergebnisse setzen und dann die Erweiterung aufrufen, die funktioniert hat.

0
Joey Morgan

Ich hatte eine ähnliche Situation. Nach zwei Stunden Mühe erkannte ich, dass ich doppelte Namensraumnamen in meinen Bibliotheken hatte. Wenn Sie die von Microsoft veröffentlichte Datei Dynamic.cs verwenden, müssen Sie lediglich den aktuellen Namespace in einen anderen Namen umbenennen. Dies wird behoben.

//Copyright (C) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace System.Linq.Dynamic    <- for example to Linq.Dynamic
{
0
Ryan

Ich hatte das gleiche Problem, auch mit externem Alias, und ich habe es als Compiler-Fehler gemeldet bei Connect. Die Problemumgehung besteht vorerst darin, auf die Syntax der Erweiterungsmethode zu verzichten.

Der Fehler ist für Visual Studio 2010 behoben.

0
Ben Challenor

Es ist wirklich ein Compiler-Fehler.

Ich hatte das gleiche Problem und habe es gelöst, indem ich das Projekt gereinigt und neu aufgebaut habe. Danach verschwand das Problem.

0
DOHXEHAPO

Eine Lösung wäre, den gesamten Code in eine Teilklasse zu verschieben, die den ReSharper-Code verwendet. Dort würden Sie nur den ReSharper-Namespace und nicht System.Core importieren.

Im Rest der partiellen Klasse importieren Sie alle anderen Namespaces, die Sie benötigen, einschließlich System.Core, jedoch nicht den ReSharper-Namespace.

0
Fabrice