2

サーバーコードで列挙型を宣言しましたが、クライアントコードで列挙型を使用できるようにしたいと考えています。残念ながら、それはいくつかの理由で自動生成されていません。私の列挙型は、次の例のように宣言されています。

[DataContract]
public enum MyEnum {
    [EnumMember]
    First = 1,
    [EnumMember]
    Second = 2
}

これはクラス内で宣言されていませんが、自動生成されるいくつかのクラス(すべて同じ名前空間内)と一緒に宣言されています。クライアントコードでこれらのクラスを使用しても問題はありませんが、この列挙型は生成されていないため、使用できません。ヘルプ!

ありがとう!!

編集:

現在のところ、このサービスは「MyEnum」をパラメーターとして受け取ることも、関数から返すこともありません。それが私の問題です。サーバーコードのいくつかの場所で使用されており、クライアントコードのいくつかの場所でも使用したいと思います(既存の構成をコピーして貼り付ける必要はありません)。

4

5 に答える 5

2

私はこの正確な問題に遭遇しました。解決策はそれほど単純ではありませんでした。

私は次のことをしました:

  • サービス用に独自のServiceHostFactoryを定義する
  • 工場では、サービスコントラクトの説明からメタデータの動作を取得し、組み込みのMetadataExporterをカスタム実装に置き換えます
  • カスタムMetaDataExporterで、GetGeneratedMetadata関数をオーバーライドし、サービス用に生成されたXMLスキーマを直接操作します
  • サービスによって公開されたタイプのリフレクションを使用して、必要なすべての列挙型を検出し、それらをスキーマに追加できました
  • これで、サービスをクライアントに追加してプロキシを構築すると、列挙型が含まれます
  • 含めたい列挙型に適用できる独自のカスタムDataEnumAttributeを定義することで、プロセスを汎用化しました

私の考えでは、これはwcfサービスメタデータジェネレーターの欠陥です。タイプで定義された列挙型を追加するように構成可能である必要がありますが、コントラクトプロパティによって参照されることはありません。

完全なコードは投稿するには少し長すぎますが、基本的な考え方は次のとおりです。

Public Class CustomMetaDataFactory
Inherits System.ServiceModel.Activation.ServiceHostFactory

  '----------------------------------------------------------------------------
  ' CreateServiceHost (Overridden)
  '----------------------------------------------------------------------------
  Protected Overrides Function CreateServiceHost(ByVal serviceType As System.Type, _
                                                 ByVal baseAddresses() As System.Uri) _
                                                   As System.ServiceModel.ServiceHost
    '--------------------------------------------------------------------------
    ' Local Variables
    '--------------------------------------------------------------------------
    Dim host As System.ServiceModel.ServiceHost = _
      MyBase.CreateServiceHost(serviceType, baseAddresses)
    Dim smb As ServiceMetadataBehavior
    Dim bFound As Boolean = False

    '--------------------------------------------------------------------------
    ' Attach a meta data behaviour so that the service will publish
    ' wsdl and xsd descriptions
    '--------------------------------------------------------------------------
    Dim behavior As IServiceBehavior


    For Each behavior In host.Description.Behaviors
      If (TypeOf behavior Is ServiceMetadataBehavior) Then
        smb = CType(behavior, ServiceMetadataBehavior)
        '------------------------------------------------------------------------
        ' Replace the default MetadataExporter with our custom implementation
        '------------------------------------------------------------------------
        smb.MetadataExporter = New CustomWsdlExporter
        bFound = True
        Exit For
      End If
    Next

    If (Not bFound) Then
      smb = New ServiceMetadataBehavior
      smb.HttpGetEnabled = True
      smb.HttpGetUrl = baseAddresses(0)
      '--------------------------------------------------------------------------
      ' Replace the default MetadataExporter with our custom implementation
      '--------------------------------------------------------------------------
      smb.MetadataExporter = New CustomWsdlExporter
      host.Description.Behaviors.Add(smb)
    End If

    Return host

  End Function

End Class

Public Class CustomWsdlExporter
  Inherits WsdlExporter

  '----------------------------------------------------------------------------
  ' ExportContract
  '----------------------------------------------------------------------------
  Public Overrides Sub ExportContract(ByVal contract As System.ServiceModel.Description.ContractDescription)
    '--------------------------------------------------------------------------
    ' Local Variables
    '--------------------------------------------------------------------------
    Dim op As OperationDescription

    ' iterate the operations, collecting the return type and parameter types
    For Each op In contract.Operations
    ' Add code here to reflect the operations and the types used by them
    Next

    MyBase.ExportContract(contract)
  End Sub

  '----------------------------------------------------------------------------
  ' GetGeneratedMetadata
  '----------------------------------------------------------------------------
  Public Overrides Function GetGeneratedMetadata() As System.ServiceModel.Description.MetadataSet
    '--------------------------------------------------------------------------
    ' Local Variables
    '--------------------------------------------------------------------------
    Dim schemas As XmlSchemaSet
    Dim schema As XmlSchema

    schemas = MyBase.GeneratedXmlSchemas
    If (schemas IsNot Nothing AndAlso schemas.Count > 0) Then
      For Each schema In schemas.Schemas
    ' Add code here to manipulate each XML schema generated for the service
      Next
    End If
    Return MyBase.GetGeneratedMetadata()

  End Function



End Class
于 2011-04-05T13:29:09.510 に答える
2

これに関連して見つけたものを投入すると思いました。KnowType属性について読むと、デシリアライザーは、KnownTypeで参照する型が渡される可能性があると考える理由が必要です。デシリアライザーがデータコントラクトまたはメソッドパラメーターのすべての型を認識している場合、デシリアライザーはその仕事をするために悪臭を放つ「KnownTypes」を必要としないため、それらを無視します。サービスのどこかにタイプとして定義された「オブジェクト」がある場合..ええと、貧弱な古いデシリアライザーは、そこからどのタイプが来るのか見当がつかないので、既知のタイプをすべて使い果たして吐き出します。クライアントプロキシ。

ハック?そうそう。あなたが必死なら、それは機能しますか?うん。

于 2011-08-15T13:44:58.293 に答える
1

この問題について私が思いついた最も簡単な解決策は、MyEnumパラメーターを受け取ってそれを返す単純なWCF関数を作成することでした。その結果、「MyEnum」がクライアントに公開されます。

//Declaration
[DataContract]
MyEnum GetMyEnum(MyEnum value);

//Definition
public MyEnum GetMyEnum(MyEnum value){
    return value;
}

これを必要としない、および/またはより優雅な代替案をいただければ幸いです。

于 2009-06-26T17:15:50.560 に答える
0

使用していると思われるクライアントサーバーモデルの分離に関するものでは、この列挙型や他のクラスのように、両方で使用されるアイテムを格納するために、クライアントとサーバー間で共有アセンブリが必要です。これを行うための良い方法は、インターフェイスを使用することです(列挙型には役立ちませんが、共有アセンブリにスローすることができます)。

于 2009-06-26T17:23:34.733 に答える
0

私にはいくつかのオプションがあるようです。サービスインターフェイス(ServiceContract)が列挙型と等しいtypeofのパラメーターまたは戻り値を公開する場合、クライアントはサービス定義を介して列挙型を取得します。実際には、svcutilによってWSDLから生成されたクライアント側のコードには、インターフェースで使用されるものに対応する列挙型が含まれます。

列挙型がサービスのパブリックインターフェイスのどこにも使用されていない場合は、共有型のアセンブリに依存できます。

于 2009-06-26T19:05:38.033 に答える