Вопрос

У меня есть библиотека классов с некоторыми методами расширения, написанными на C #, и старый веб-сайт, написанный на VB.

Я хочу вызвать свои методы расширения из кода VB, но они не отображаются в intelisense, и я получаю ошибки компиляции при посещении сайта.

У меня есть все необходимое Импортs потому, что другие классы, содержащиеся в тех же пространствах имен, прекрасно отображаются в Intelisense.

Есть какие-нибудь предложения

Редактировать: Дополнительная информация, которая поможет с некоторыми комментариями.

моя реализация выглядит примерно так

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

    }
}

и мое использование выглядит следующим образом

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.
Это было полезно?

Решение

Это работает для меня, хотя есть несколько причуд. Сначала я создал библиотеку классов C # для .NET 3.5. Вот единственный код в проекте:

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);
    }
  }
}

Затем я создал консольное приложение VB для .NET 3.5 и добавил ссылку на мой проект на C #. Я переименовал Module1.vb в Test.vb, и вот код:

Imports ExtensionLibrary

Module Test

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

End Module

Это компилируется и запускается. (Я бы назвал метод Reverse (), но я не был уверен, может ли VB магически иметь обратные способности уже где-то - я не эксперт по VB по мелу.)

Изначально мне не предлагали ExtensionLibrary для импорта из Intellisense. Даже после сборки < Imports ExtensionLibrary " отображается серым цветом, а лампочка дает возможность удалить предположительно избыточный импорт. (Это нарушает проект.) Возможно, это ReSharper, а не Visual Studio.

Короче говоря, это можно сделать, и это должно работать просто отлично. Я не думаю, что проблема в том, что вы либо используете старую версию VB, либо ваш проект не ориентирован на .NET 3.5?

Как отмечалось в комментариях: есть еще одна особенность, которая заключается в том, что методы расширения не будут найдены, когда целевой тип во время компиляции является объектом .

Другие советы

Методы расширения являются просто синтаксическим сахаром для статических методов. Так

public static string MyExtMethod(this string s)

может вызываться как в VB.NET, так и в C # с помощью

MyExtMethod("myArgument")

ОК.Основываясь на сообщении об ошибке, вы определенно нет используйте самую последнюю версию VB (VB 9!) или ошибка вообще не связана с этой проблемой, потому что тогда вы получите другую ошибку, если метод не был найден:

Ошибка 1 'q' не является членом 'String'.

Imports x.y

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

Я думаю, что у меня есть столкнулся с аналогичной проблемой:VB.Net вполне рад скомпилировать с помощью методов расширения и оставить их для вывода во время выполнения, если Option Strict выключен.

Однако VB.Net похоже, что ему действительно не нравятся методы расширения для базовых типов.Вы не можете расширить Object и это не сможет решить проблему, если вы это сделаете:

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");

Однако это идет не так, как надо в VB.Net:

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

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

Это компилируется без ошибок, но во время выполнения происходит сбой, потому что Something это не метод String - компилятору не удалось заменить синтаксический сахар метода расширения статическим вызовом Utility.Something.

Вопрос в том, почему?Ну, в отличие от C#, VB.Net не могу обработать какое-либо расширение для Object!Допустимый метод расширения в C # вводит в заблуждение компилятор VB.Net.

В качестве общего правила VB.Net я бы избегал использования методов расширения с любым из базовых типов .Net (Object, String, Integer, и т.д.).Вы также должны быть осторожны с Option Infer поскольку, хотя он включен по умолчанию в Visual Studio, он по умолчанию отключен для компиляции из командной строки, VBCodeProvider, и, возможно, на веб-сайтах (в зависимости от вашего web.config).Когда он отключен, все в VB.Net считается Object и все методы расширения будут оставлены до времени выполнения (и, следовательно, завершатся сбоем).

Я думаю, что Microsoft действительно упустила момент, когда они добавили методы расширения в VB.Net, я думаю, что это была запоздалая мысль попытаться (и потерпеть неудачу) привести его в соответствие с C #.

Я не знаю, можете ли вы вызывать их в той же точечной нотации, что и в C #, но я думаю, что методы статического расширения будут отображаться как статические функции с аргументом fist в качестве расширенного типа. Таким образом, вы должны иметь возможность вызывать фактически класс в VB с помощью:

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

Где в C # вы бы просто написали:

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

StaticClass - это имя статического класса, в котором вы определили методы расширения.

... и старый веб-сайт, написанный на VB.

Означает ли “старый” здесь, возможно, что вы также используете здесь старую версию VB?В любом случае, поскольку методы расширения являются просто ванильными статическими (“Shared”) методы, украшенные атрибутом, позволяют следует будьте в состоянии вызвать их в любом случае.

Если это невозможно, вы либо пытаетесь назвать их “стилем расширения” в старой версии VB, либо ссылаетесь на неправильную версию вашей сборки C #.

Редактировать:ты уверен, что ты Importиспользуя весь пространство имен, т.е. x.y и не только x?VB может получить доступ к вложенным пространствам имен проще, чем C #, поэтому вы можете использовать классы из пространства имен x.y используя следующий код в VB.Однако для того, чтобы методы расширения работали, необходимо полный путь должен быть Importизд.

Imports x
Dim x As New y.SomeClass()

Две вещи, которые нужно проверить:

<Ол>
  • Вы нацеливаетесь на .Net 3.5
  • Вы ссылаетесь на DLL
  • Некоторые инструменты могут неправильно предлагать методы расширения для проектов, которые их не поддерживают.

    Я столкнулся с той же проблемой и мог случайно наткнуться на решение. Если бы я использовал

    x.y.r.q()
    

    , он также выдал ту же ошибку для меня. Но если я импортировал x.y, это сработало, так что

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

    было хорошо.

    Так что, очевидно, вы должны импортировать его в объявление, чтобы оно работало.

    Это было довольно давно, и я не могу понять, как я это решил, но, разумеется, это была ошибка пользователя. Я, вероятно, перезагрузил свой компьютер, и он ушел.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top