2

ファイルをアップロードするための WCF WebMethod を作成しています。そのファイルのスニペットを Web から取得しました。WCF インターフェイスは次のようになります。

<ServiceContract()>
Public Interface ITransferService

    <OperationContract()>
    Sub UploadFile(ByVal request As RemoteFileInfo)

End Interface

<MessageContract()>
Public Class RemoteFileInfo
    Implements IDisposable

    <MessageHeader(MustUnderstand:=True)>
    Public FileName As String

    <MessageHeader(MustUnderstand:=True)>
    Public Length As Long

    <MessageBodyMember(Order:=1)>
    Public FileByteStream As System.IO.Stream

    Public Sub Dispose() Implements IDisposable.Dispose
        If FileByteStream IsNot Nothing Then
            FileByteStream.Close()
            FileByteStream = Nothing
        End If
    End Sub

End Class

ASP.NET 内では、Web メソッドが消費されると、何らかの理由で、インターフェイスが のインスタンス化の一部として使用されている場合にのみ機能しますRemoteFileInfo

Protected Sub btn_Click(sender As Object, e As EventArgs) Handles btn.Click
    If fu.HasFile Then
        Dim fi As New System.IO.FileInfo(fu.PostedFile.FileName)

        ' this is the line in question --------------
        Dim cu As ServiceReference1.ITransferService = New ServiceReference1.TransferServiceClient()
        ' -------------------------------------------

        Dim uri As New ServiceReference1.RemoteFileInfo()
        Using stream As New System.IO.FileStream(fu.PostedFile.FileName, IO.FileMode.Open, IO.FileAccess.Read)
            uri.FileName = fu.FileName
            uri.Length = fi.Length
            uri.FileByteStream = stream
            cu.UploadFile(uri)
        End Using
    End If
End Sub

TransferService次のアプローチを使用してインスタンスを作成できない理由を誰でもアドバイスできますか:

Dim cu As New ServiceReference1.TransferServiceClient()

上記を試すと、次の行が壊れます。

cu.UploadFile(uri)

...そして UploadFile は、この署名を使用するメソッドがなくても、3 つのパラメーター (FileName、Length、FileByteStream) で呼び出す必要があります。

このクラスのインスタンスを作成するときにインターフェイスが必要なのはなぜですか?

4

2 に答える 2

2

[サービス参照の追加] ダイアログでサービスのプロキシを作成すると、デフォルトで、プロキシ作成コードがメッセージ コントラクトを「アンラップ」します。プロキシのサーバー側で定義したとおりにメッセージ コントラクトを表示する場合は、[詳細設定] タブを選択し、[常にメッセージ コントラクトを生成する] オプションをオンにする必要があります。これにより、クライアントでもメッセージ コントラクトを取得できます。

于 2013-01-03T20:00:45.607 に答える
1

問題はMessageContract、パラメーターとして a が検出された場合、WCF クライアントの生成では、既定でメッセージング スタイルのインターフェイスを実装する必要があると見なされ、メッセージ コントラクトから個別のプロパティがクライアント側インターフェイスの一部として提供されることです。

MSDNのUsing Messaging Contractsの記事には、メッセージング コントラクトで何ができるかについての非常に詳細な説明が含まれており、Microsoft がこの既定の動作を選択したのは、メッセージで遊べるいくつかの "ゲーム" があるためだと思われます。

ただし、クライアント側で UploadFile 用に生成されたコードを調べると、何が起こっているのかを説明するのに役立つ興味深いヒントがいくつかあります。

1 つ目は、インターフェイスの UploadFile メソッドのコメントです。

    'CODEGEN: Generating message contract since the operation UploadFile is neither RPC nor document wrapped.
    ...
    Function UploadFile(ByVal request As ServiceReference1.RemoteFileInfo) As ServiceReference1.UploadFileResponse

これは、メッセージ コントラクトの実装が異なる場合、コントラクトが別の方法で生成されることを意味します。

2 つ目は、実際にサービス呼び出しを行うために使用されるコードに特別なことは何もないことがわかるということです。

    Public Sub UploadFile(ByVal FileName As String, ByVal Length As Long, ByVal FileByteStream As System.IO.Stream)
        Dim inValue As ServiceReference1.RemoteFileInfo = New ServiceReference1.RemoteFileInfo()
        inValue.FileName = FileName
        inValue.Length = Length
        inValue.FileByteStream = FileByteStream
        Dim retVal As ServiceReference1.UploadFileResponse = CType(Me,ServiceReference1.ITransferService).UploadFile(inValue)
    End Sub

したがって、この場合、コードは生成されたコードとまったく同じことを行っています。しかし、MessageContract がもっと複​​雑な場合は、そうではなくなるのではないかと思います。

だから、あなたの質問のために:

次のアプローチを使用して TransferService のインスタンスを作成できない理由を誰かアドバイスできますか...

メソッド呼び出しの実装がコードと同等の機能であることを確認する限り、このアプローチを採用しない理由はありません。

クライアントでメソッドのデフォルトの生成を変更するためのオプションがいくつかあります。

1)クラスMessageContractから属性を削除します。RemoteFileInfo

2) 直感に反しているように見えますが、 Configure Service Reference Dialog BoxAlways generate message contractsのチェックボックスをオンにすることができます。

于 2013-01-04T02:56:56.463 に答える