在ASP.NET网站项目中,如何在C#类中使用来自同一项目的VB类?

3
我有一个ASP.NET网站项目,其中我使用了VB.Net和C#类文件。我在App_Code目录中为每种语言的类包含了单独的子文件夹。
然而,虽然我可以成功地在VB类中使用C#类,但我不能做相反的事情:在C#类中使用VB类。
因此,举个例子,我可能有两个这样的类:
Public Class VBTestClass
    Public Sub New()
    End Sub

    Public Function HelloWorld(ByVal Name As String) As String
        Return Name
    End Function
End Class

public class CSTestClass
{
    public CSTestClass()
    {
    }
    public string HelloWorld(string Name)
    {
        return Name;
    }

}

我可以使用“Imports”语句在我的VB类中使用CS类。因此,这个方法可以很好地工作:

Imports CSTestClass
Public Class VBTestClass
    Public Sub New()
    End Sub

    Public Function HelloWorld(ByVal Name As String) As String
        Return Name
    End Function

  Private Sub test()
      Dim CS As New CSTestClass
      CS.HelloWorld("MyName")
   End Sub
End Class

但是在我的C#中使用VB类,使用"using"语句并不起作用:
using VBTestClass;
public class CSTestClass
{
      public CSTestClass()
      {
  }

     public string HelloWorld(string Name)
    {
        return Name;
    }
}

我遇到了一个错误,提示“找不到VBTestClass类型或命名空间”。我错过了什么吗?
4个回答

2

使用/导入语句作为跳过完全限定命名空间的快捷方式是最好的方法。在 VB 和 C# 中,行为都是一样的。

考虑以下示例:

完全限定命名空间:

void DoSomething()
{
    var p = new Interfaces.CPDATA.DataHolders.Placement(); 
}

跳过命名空间:

using Interfaces.CPDATA.DataHolders; 
void DoSomething()
{
    var p = new Placement(); 
    var t = new Trade(); 
}    

还有一个小技巧

using data = Interfaces.CPDATA.DataHolders; 
void DoSomething()
{
    var p = new data.Placement(); 
    var t = new data.Trade(); 
}   

以及一个替换技巧:

using t = Interfaces.CPDATA.DataHolders.Placement; 
void DoSomething()
{
    var p = new t(); // happy debagging
}   

关于ASP.NET App_Code文件夹中不同语言的代码文件:不要使用它们。因为:
  • 在使用Web应用程序项目时它们不起作用
  • 在使用csc或vbc编译器进行Visual Studio之外的持续集成项目时,它们将无法编译
  • 它们通常会在基础设施方面给你带来很多痛苦。
最好的方法是为各自的语言创建单独的类库项目并使用它们。
此外,在从Visual Studio和IIS下运行此类项目时会发生许多有趣的事情。如果你感兴趣,可以查看各种文件。
\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\{project name}\{tempname} 

这应该能让您了解asp.net引擎如何组合aspx页面的代码文件。

有了这些无用信息,我们现在可以说,在相同的命名空间语句“Imports CSTestClass”中拥有CSTestClass类并不是真正有用的。良好的编码风格应该是将它们全部包含在命名空间语句MyWebProject.VbCode和MyWebProject.CsCode中。然后语句“using MyWebProject.VbCode”和“Imports MyWebProject.CsCode"对于编译器来说更有意义。


2
我认为我找到了问题所在,似乎没有反射你无法将其作为交叉引用。原因很简单,取决于您定义代码子目录的顺序,我认为您是这样做的:
<codeSubDirectories>
    <add directoryName="CSCode"/>
    <add directoryName="VBCode"/>
</codeSubDirectories>

我们知道每个目录都将构建到不同的程序集中,并且根据您的设置,它们将从上到下一个接一个地构建。因此,由于您首先定义了CSCode文件夹,因此它将首先构建,然后编译器开始构建VBCode,因此使用CS类是可以的,因为它可以找到要引用的程序集。
但是,如果您反过来做,正如您提到的引用VB代码在CS中,它首先构建CSCode文件夹,此时VBCode的程序集不存在,因此会抛出异常。
因此,为使其与使用VB的CS正常工作,只需简单地更改文件夹设置顺序:
<codeSubDirectories>
    <add directoryName="VBCode"/>
    <add directoryName="CSCode"/>
</codeSubDirectories>

但这样你将失去使用任何VB中的CS类的能力,因为此时VBCode首先编译。

所以我的建议是使用反射在运行时加载它,这样编译器就可以让你通过。

希望我的解释足够清楚。

谢谢。


0

using语句是用于命名空间而非类名的,将VBClass放到一个命名空间中,然后使用"using"语句:

Namespace MyFoo
Public Class VBTestClass 
    Public Sub New() 
    End Sub 

    Public Function HelloWorld(ByVal Name As String) As String 
        Return Name 
    End Function 
End Class
End Namespace

现在用C#:

using MyFoo;

...

0

关键在于Imports关键字与using关键字的工作方式不同。

using关键字只能用于指定命名空间,而Imports关键字也可以用于指定类。

因此,Imports CSTestClass指定该类中的类、接口和枚举应该可用,但该类不包含任何这些内容,因此不需要Imports语句。

当您尝试使用using VBTestClass时,它将无法工作,因为VBTestClass不是命名空间。

因此,只需删除Importsusing语句,就可以正常工作。由于这些类在同一个程序集中,它们已经知道彼此的存在。


非常感谢 - 提供了非常有用的信息。然而,我已经尝试将VB类包装在命名空间中(根据之前的答案),并删除了导入和使用语句(仅直接使用类,假设它们在同一程序集中彼此知道)。然而,我仍然遇到了相同的问题... - Proposition Joe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接