Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/wcf/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 使用Excel VBA中包含DataContract的wcf服务_Vb.net_Wcf_Excel_Vba - Fatal编程技术网

Vb.net 使用Excel VBA中包含DataContract的wcf服务

Vb.net 使用Excel VBA中包含DataContract的wcf服务,vb.net,wcf,excel,vba,Vb.net,Wcf,Excel,Vba,你读了标题,呻吟着。没关系。我也是。但我们按要求做,对吗?我需要构建一个可以从Excel中通过名字对象访问的服务(2003,但我假设任何版本的Excel都应该支持此功能)。目前,我所要做的就是让一个电子表格将数据发布到远程机器上运行的Windows服务的WCF服务。因为需要用比VBA更复杂的方法检索数据,所以我决定建立一个数据契约。这是我的代码(目前这只是一个概念证明,但它与完成后的外观密切相关) 以下是与WCF相关的内容: Imports System.ServiceModel Imports

你读了标题,呻吟着。没关系。我也是。但我们按要求做,对吗?我需要构建一个可以从Excel中通过名字对象访问的服务(2003,但我假设任何版本的Excel都应该支持此功能)。目前,我所要做的就是让一个电子表格将数据发布到远程机器上运行的Windows服务的WCF服务。因为需要用比VBA更复杂的方法检索数据,所以我决定建立一个数据契约。这是我的代码(目前这只是一个概念证明,但它与完成后的外观密切相关)

以下是与WCF相关的内容:

Imports System.ServiceModel
Imports System.Runtime.Serialization

<ServiceContract()>
Public Interface IWCF

    <OperationContract()>
    Sub PutData(ByVal what As String)

    <OperationContract()>
    Function GetWhats() As TheWhats()

End Interface

<DataContract()>
Public Class TheWhats
    <DataMember()> Public Property Timestamp As DateTime
    <DataMember()> Public Property TheWhat As String
End Class

Public Class WCF
    Implements IWCF

    Shared Whats As New List(Of TheWhats)

    Public Sub PutData(ByVal what As String) Implements IWCF.PutData
        Whats.Add(New TheWhats With {.Timestamp = Now, .TheWhat = what})
    End Sub

    Public Function GetWhats() As TheWhats() Implements IWCF.GetWhats
        Return Whats.ToArray
    End Function
End Class
如果我包括
DataContract
属性和返回数据合约对象的函数,我的vba代码在
Public Sub-PutData
方法中失败,原因如下:

MessagePartDescription Name='GetWhatsResult'命名空间的实例='http://tempuri.org/'不能在此上下文中使用:未设置必需的'Type'属性。“

如果我取出DataContract并注释掉服务定义中的函数,我就没事了。我不打算在Excel中使用
GetWhats()
函数。但我猜它需要
TheWhats
的类型定义


据我所知,一种解决方案似乎是将其作为COM对象并引用DLL。然而,对于我的环境来说,这不是一个可行的解决方案。有没有其他方法可以解决这个问题?

我们还没有遇到过这种特定的情况,但我们在WCF上做了大量工作,我们可以控制服务和消费者(silverlight、平板电脑操作系统、mono中的ipad应用程序等)

我们使用的一般解决方案是在管道两端的相同名称空间中具有相同的类。我不能百分之百确定这在您的环境中是否有效,但在VBA中重新创建Whats类并看看这是否对您有帮助可能是值得的


如果有,并且VBA支持,您可以将类移动到它自己的文件中,并从服务和客户端项目引用它。

好的,回答了我自己的问题。解决方案(至少在我的情况下)是拆分接口,并让我的服务类实现这两个接口。这是我的新接口文件:

Imports System.ServiceModel
Imports System.Runtime.Serialization

<ServiceContract()>
Public Interface IWCF_WriteOnly

    <OperationContract()>
    Sub PutData(ByVal what As String)

End Interface

<ServiceContract()>
Public Interface IWCF_ReadOnly

    <OperationContract()>
    Function GetData() As TheWhats()

End Interface

<DataContract()>
Public Class TheWhats
    <DataMember()> Public Property Timestamp As DateTime
    <DataMember()> Public Property TheWhat As String
End Class

Public Class WCF
    Implements IWCF_WriteOnly
    Implements IWCF_ReadOnly

    Shared Whats As New List(Of TheWhats)

    Public Sub PutData(ByVal what As String) Implements IWCF_WriteOnly.PutData
        Whats.Add(New TheWhats With {.Timestamp = Now, .TheWhat = what})
    End Sub

    Public Function GetData() As TheWhats() Implements IWCF_ReadOnly.GetData
        Return Whats.ToArray
    End Function
End Class

我用WCF测试客户端测试了这个配置。我必须手动向它提供mex端点,但当我这样做时,它同时获取了两份合同。我使用
PutData
方法填充了一点服务类,然后进入Excel并填充了更多。我回到WCF测试客户机,运行
GetData
函数,它返回了从测试客户机和Excel添加的所有项目。

昨晚我有了另一个想法。假设我创建了两个不同的接口——一个“只写”接口,Excel可以安全地调用它而不必担心额外的类,另一个“服务”接口向客户机提供更多细节,包括这个类定义?这样Excel就不必知道数据契约之类的事情了——它只需将一个字符串发布到一个服务,然后就可以使用它了。我来试试。昨晚我有了另一个想法,可能是一种笨拙的方式,但它允许我纯粹通过代码来实现这一点。请看我上面的评论。谢谢你,你帮了我很大的忙!
Private Const pConxString As String = _
    "service:mexAddress=""net.tcp://localhost:7891/Test/WcfService1/Service1/mex"", " & _
    "address=""net.tcp://localhost:7891/Test/WcfService1/Service1/"", " & _
    "binding=""NetTcpBinding_IService1"", bindingNamespace = ""http://tempuri.org/"", " & _
    "contract=""IService1"", contractNamespace=""http://tempuri.org/"""

Public ServiceObject As Object

Private Sub Class_Initialize()
    Set ServiceObject = GetObject(pConxString)
End Sub

Public Sub PutData(ByVal what As String)
    ServiceObject.PutData what
End Sub

Private Sub Class_Terminate()
    Set ServiceObject = Nothing
End Sub
Imports System.ServiceModel
Imports System.Runtime.Serialization

<ServiceContract()>
Public Interface IWCF_WriteOnly

    <OperationContract()>
    Sub PutData(ByVal what As String)

End Interface

<ServiceContract()>
Public Interface IWCF_ReadOnly

    <OperationContract()>
    Function GetData() As TheWhats()

End Interface

<DataContract()>
Public Class TheWhats
    <DataMember()> Public Property Timestamp As DateTime
    <DataMember()> Public Property TheWhat As String
End Class

Public Class WCF
    Implements IWCF_WriteOnly
    Implements IWCF_ReadOnly

    Shared Whats As New List(Of TheWhats)

    Public Sub PutData(ByVal what As String) Implements IWCF_WriteOnly.PutData
        Whats.Add(New TheWhats With {.Timestamp = Now, .TheWhat = what})
    End Sub

    Public Function GetData() As TheWhats() Implements IWCF_ReadOnly.GetData
        Return Whats.ToArray
    End Function
End Class
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.web>
    <compilation debug="true"></compilation>
  </system.web>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="GenericBehavior" name="DataCollectionService.WCF">
        <endpoint address="wo" binding="netTcpBinding" contract="DataCollectionService.IWCF_WriteOnly" />
        <endpoint address="ro" binding="netTcpBinding" contract="DataCollectionService.IWCF_ReadOnly" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost:9100/DataCollectionService/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="GenericBehavior">
          <serviceMetadata httpGetEnabled="false"/>
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
Private Const pConxString As String = _
    "service:mexAddress=""net.tcp://localhost:9100/DataCollectionService/Mex"", " & _
    "address=""net.tcp://localhost:9100/DataCollectionService/wo"", " & _
    "binding=""NetTcpBinding_IWCF_WriteOnly"", bindingNamespace = ""http://tempuri.org/"", " & _
    "contract=""IWCF_WriteOnly"", contractNamespace=""http://tempuri.org/"""