0

WCFサービスには1つの方法しかありません。

[ServiceContract(Name = "Service", Namespace = "http://myservice/")]
[ServiceKnownType("GetServiceKnownTypes", typeof(Service))]
public interface IService {
     Response Execute(Request request);
}

public class Service : IService {
     public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider) {
        return KnownTypesResolver.GetKnownTypes();
     }

     public Response Execute(Request request) { 
         return new MyResponse { Result = MyEnumHere.FirstValue }; 
     }
}

RequestResponseクラスの両方にParameterCollectionメンバーが含まれています。

[Serializable]
[CollectionDataContract(Name = "ParameterCollection", Namespace = "http://myservice/")]
[KnownType("GetKnownTypes")]
public class ParameterCollection : Dictionary<string, object> {
        private static IEnumerable<Type> GetKnownTypes()
        {
            return KnownTypesResolver.GetKnownTypes();
        }
}

のサブクラスRequestResponseその値をParameterCollection値バッグに格納します。

私はKnownTypesResolverクラスを使用して、すべてのServiceオブジェクトに型情報を提供しています。

public static class KnownTypesResolver {
     public static IEnumerable<Type> GetKnownTypes()
     {
         var asm = typeof(IService).Assembly;
         return asm
             .GetAllDerivedTypesOf<Response>() // an extension method
             .Concat(new Type[] {
                 typeof(MyEnumHere),
                 typeof(MyEnumHere?),
                 typeof(MyClassHere),
                 typeof(MyClassListHere),
             });
     }
}

私が間違っていなければ、クライアント側で明確に定義されたクラスを生成するためのプロキシクラス生成ツールの適切な型情報がすべてに含まれている必要があります。ただし、Responseサブクラスの1つ(つまりMyResponse)になどの列挙値が含まれている場合は常にMyEnumHere、WCFはデシリアライザーがMyEnumHere値を認識していないと文句を言い始めます。持っている必要があります。KnownTypeAttribute私はまさにこの理由でを提供しました。

クライアント側のプロキシクラスにはMyEnumHere、Reference.csファイルに列挙型があります。問題は、ParameterCollectionクラスにKnownTypeAttributesが生成されていないことです。

私は手作業で編集し、生成されたReference.csファイルに次の行を含めることにしました。

//>
[KnownTypeAttribute(typeof(MyEnumHere))]
[KnownTypeAttribute(typeof(MyEnumHere?))]
[KnownTypeAttribute(typeof(MyClassHere))]
[KnownTypeAttribute(typeof(MyClassListHere))]
//<
public class ParameterCollection : Dictionary<string, object> { /* ... */ }

生成されたファイルを手作業で編集するのは恐ろしいことです。しかし、これによりクライアントは機能します。私は何が間違っているのですか?生成されたVSプロキシクラスが最初から正しくなるように、Serviceオブジェクトを定義するにはどうすればよいですか?

御時間ありがとうございます。

4

2 に答える 2

1

WCFは相互運用性がないため、うまく機能しませんDictionaryArray、またはカスタムコレクションを使用Listして、データが適切にシリアル化されていることを確認できます。

以下のコードは、List<ParamCollectionElement>の代わりにを使用しDictionaryます。また、いくつかの冗長な属性を削除しました。

[DataContract]
public class Request
{
    [DataMember]
    public ParameterCollection ParameterCollection { get; set; }
}

[DataContract]
public class Response
{
    [DataMember]
    public ParameterCollection ParameterCollection { get; set; }
}

[DataContract]
public class MyResponse : Response
{
    [DataMember]
    public MyEnumHere Result { get; set; }
}

public class ParamCollectionElement
{
    public string Key { get; set; }
    public object Value { get; set; } 
}


[CollectionDataContract(Name = "ParameterCollection")]
public class ParameterCollection : List<ParamCollectionElement> 
{

}

public static class KnownTypesResolver
{
    public static IEnumerable<Type> GetKnownTypes()
    {
        return
            new Type[] {
                typeof(MyEnumHere),
                typeof(MyEnumHere?),
                typeof(Request),
                typeof(Response),
                typeof(MyResponse)
            };
    }
}

[DataContract]
public enum MyEnumHere
{
    [EnumMember]
    FirstValue,
    [EnumMember]
    SecondValue
}

[ServiceKnownType("GetServiceKnownTypes", typeof(Service))]
[ServiceContract(Name = "Service")]
public interface IService
{
    [OperationContract]
    Response Execute(Request request);
}

public class Service : IService
{
    public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
    {
        return KnownTypesResolver.GetKnownTypes();
    }

    public Response Execute(Request request)
    {
        var result = new MyResponse
        {
            Result = MyEnumHere.FirstValue,
            ParameterCollection = new ParameterCollection()
        };

        result.ParameterCollection.Add(new ParamCollectionElement {Key = "one", Value = MyEnumHere.FirstValue});
        result.ParameterCollection.Add(new ParamCollectionElement { Key = "two", Value = new Response() });
        return result;
    }
} 
于 2012-06-19T20:10:53.917 に答える
0

[DataContract]列挙型と[EnumMember]各列挙型メンバーにあることを確認してください。

[DataContract]
public enum MyEnumHere
{
    [EnumMember]
    SomeValue,
    [EnumMember]
    OtherValue,
    [EnumMember]
    OneMoreValue
}

これにより、Reference.csファイルを手動で変更しなくても、クライアントでプロキシ列挙型が(そのメンバー値とともに)構築されるはずです。

于 2012-06-19T20:20:00.573 に答える