【发布时间】:2011-11-03 21:13:02
【问题描述】:
你读了标题并呻吟着。没关系。我也是。但是我们按照我们的要求去做,对吧?我需要构建一个可以通过 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
我的 app.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true"></compilation>
</system.web>
<system.serviceModel>
<services>
<service name="DataCollectionService.WCF">
<endpoint address=""
binding="netTcpBinding"
contract="DataCollectionService.IWCF" />
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:9100/DataCollectionService/ "/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
还有我的 vba 类来处理发布的东西:
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
如果我包含 DataContract 属性和返回数据协定对象的函数,我的 vba 代码将在 Public Sub PutData 方法中失败,并显示以下内容:
“MessagePartDescription Name='GetWhatsResult' Namespace='http://tempuri.org/' 的实例不能在此上下文中使用:未设置必需的 'Type' 属性。”
如果我取出DataContract并在服务定义中注释掉函数,我很好。我不打算在 Excel 中使用 GetWhats() 函数。但我猜它想要TheWhats 的类型定义。
从我读过的内容来看,一种解决方案似乎是将其设为 COM 对象并引用 DLL。但是,这对我的环境来说不是一个可行的解决方案。有没有其他方法可以解决这个问题?
【问题讨论】:
-
昨晚我有了另一个想法。假设我创建了两个不同的接口——一个 Excel 可以安全调用而无需担心额外类的“只写”接口,以及一个向客户端提供更多详细信息(包括此类定义)的“服务”接口?这样一来,Excel 将永远不必知道数据合同之类的东西——它只需将一个字符串发布到服务并完成它。