Domanda

Ho una libreria di classi con alcuni metodi di estensione scritti in C # e un vecchio sito Web scritto in VB.

Voglio chiamare i miei metodi di estensione dal codice VB ma non compaiono in intelisense e ottengo errori di compilazione quando visito il sito.

Ho ottenuto tutti i Import necessari perché altre classi contenute negli stessi spazi dei nomi appaiono bene in Intelisense.

Eventuali suggerimenti

MODIFICA: Ulteriori informazioni per aiutare con alcuni commenti.

la mia implementazione è simile a questa

//C# code compiled as DLL
namespace x.y {
    public static class z {
        public static string q (this string s){
             return s + " " + s;
        }

    }
}

e il mio utilizzo in questo modo

Imports x.y

'...'
Dim r as string = "greg"
Dim s as string = r.q() ' does not show in intelisense
                        ' and throws error : Compiler Error Message: BC30203: Identifier expected.
È stato utile?

Soluzione

Funziona per me, anche se ci sono un paio di stranezze. Innanzitutto, ho creato una libreria di classe C # destinata a .NET 3.5. Ecco l'unico codice nel progetto:

using System;

namespace ExtensionLibrary
{
  public static class Extensions
  {
    public static string CustomExtension(this string text)
    {
      char[] chars = text.ToCharArray();
      Array.Reverse(chars);
      return new string(chars);
    }
  }
}

Quindi ho creato un'app console VB destinata a .NET 3.5 e ho aggiunto un riferimento al mio progetto C #. Ho rinominato Module1.vb in Test.vb ed ecco il codice:

Imports ExtensionLibrary

Module Test

    Sub Main()
        Console.WriteLine("Hello".CustomExtension())
    End Sub

End Module

Questo compila ed esegue. (Avrei chiamato il metodo Reverse () ma non ero sicuro che VB potesse avere magicamente delle abilità inverse già da qualche parte - non sono un esperto di VB da un lungo gesso.)

Inizialmente, non mi è stato offerto ExtensionLibrary come importazione da Intellisense. Anche dopo la creazione, "Imports ExtensionLibrary" è disattivato e una lampadina offre l'opportunità di rimuovere l'importazione apparentemente ridondante. (In questo modo si rompe il progetto.) È possibile che questo sia ReSharper piuttosto che Visual Studio, sia chiaro.

Quindi, per farla breve, può essere fatto e dovrebbe funzionare bene. Suppongo che il problema sia che stai utilizzando una versione precedente di VB o che il tuo progetto non è destinato a .NET 3.5?

Come notato nei commenti: c'è un'ulteriore stranezza, vale a dire che i metodi di estensione non saranno trovati quando il tipo di compilazione in tempo del target è Object .

Altri suggerimenti

I metodi di estensione sono solo zucchero sintattico per metodi statici. Quindi

public static string MyExtMethod(this string s)

può essere chiamato sia in VB.NET che in C # con

MyExtMethod("myArgument")

OK. In base al messaggio di errore, stai sicuramente non utilizzando la versione VB più recente (VB 9!) O l'errore non è affatto correlato a questo problema perché, se il metodo visualizzasse un altro errore non è stato trovato:

  

L'errore 1 'q' non è un membro di 'String'.

Imports x.y

'...'
Dim r As String = "greg"
Dim s As String = r.q() 'same as z.q(r) 

Penso di aver riscontrato un problema simile : VB.Net è abbastanza felice di compilare tramite metodi di estensione e lasciarli da dedurre in fase di esecuzione se Option Strict è disattivato.

Tuttavia, VB.Net non sembra apprezzare i metodi di estensione sui tipi di base. Non puoi estendere Object e non puoi risolverlo se lo fai:

C #

namespace NS
...

public static class Utility {

    public static void Something(this object input) { ...

    public static void Something(this string input) { ...

}

// Works fine, resolves to 2nd method
"test".Something();

// At compile time C# converts the above to:
Utility.Something("test");

Tuttavia, ciò va storto in VB.Net:

Option Infer On
Option Explicit On
Option Strict Off
Imports NS
...

    Dim r as String = "test" 
    r.Something()

Che si compila senza errori, ma in fase di esecuzione non riesce perché Something non è un metodo di String - il compilatore non è riuscito a sostituire lo zucchero sintattico del metodo di estensione con la chiamata statica a Utility.Something .

La domanda è perché? A differenza di C #, VB.Net non è in grado di gestire alcuna estensione per Object ! Il metodo di estensione valido in C # confonde il compilatore VB.Net.

Come regola generale VB.Net, eviterei di usare metodi di estensione con uno qualsiasi dei tipi base .Net ( Object , String , Integer , ecc.). Devi anche stare attento con Opzione Infer poiché mentre è attivato per impostazione predefinita in Visual Studio è disattivato per impostazione predefinita per le compilazioni da riga di comando, VBCodeProvider , e possibilmente nei siti Web (a seconda sul tuo web.config). Quando è spento tutto in VB.Net è considerato un Object e tutti i metodi di estensione rimarranno fino al runtime (e quindi falliranno).

Penso che Microsoft abbia davvero lasciato cadere la palla quando hanno aggiunto i metodi di estensione a VB.Net, penso che sia stato un ripensamento provare (e fallire) a renderlo coerente con C #.

Non so se puoi chiamarli nella stessa notazione punto che faresti in C #, ma penso che i metodi di estensione statici verrebbero visualizzati come funzioni statiche con l'argomento pugno come tipo esteso. Quindi dovresti essere in grado di chiamare la classe effettivamente in VB con:

StaticClass.ExtensionMethod(theString, arg1, ..., argN)

Dove in C # avresti appena scritto:

theString.ExtensionMethod(arg1, ..., argN);

Con StaticClass come nome della classe statica in cui sono stati definiti i metodi di estensione.

  

& # 8230; e un vecchio sito Web scritto in VB.

Fa & # 8220; vecchio & # 8221; qui implica forse che usi anche una vecchia versione di VB qui? Comunque, poiché i metodi di estensione sono solo metodi vanilla static (& # 8220; Shared & # 8221;) decorati con un attributo, dovresti essere in grado di chiamarli in ogni caso .

Se ciò non è possibile, prova a chiamarli & # 8220; stile estensione & # 8221; in una vecchia versione di VB o stai facendo riferimento alla versione errata del tuo assembly C #.

Modifica: sei sicuro di Importa nello spazio dei nomi intero , cioè xy e non solo x ? VB è in grado di accedere agli spazi dei nomi nidificati più facilmente di C #, quindi è possibile utilizzare le classi dallo spazio dei nomi x.y utilizzando il seguente codice in VB. Tuttavia, affinché i metodi di estensione funzionino, il percorso completo deve essere Import ed.

Imports x
Dim x As New y.SomeClass()

Due cose da controllare:

  1. Targeting .Net 3.5
  2. Stai facendo riferimento alla DLL

Alcuni strumenti potrebbero suggerire erroneamente metodi di estensione per progetti che non li supportano.

Ho riscontrato lo stesso problema e potrei essermi imbattuto accidentalmente nella soluzione. Se avessi usato

x.y.r.q()

, ha gettato lo stesso errore anche per me. Ma se ho importato x.y, ha funzionato, quindi:

using x.y;
...
r.q()

andava bene.

Quindi apparentemente devi importarlo nella dichiarazione per farlo funzionare.

Questo è successo un po 'di tempo fa e non riesco davvero a risolverlo, ma inutile dirlo, è stato un errore dell'utente. Probabilmente ho riavviato il mio computer e tutto è andato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top