首頁>Program>source

我正在尝試實現一个服務協定,其中包含采用通用介面的方法,並且该通用介面本身被賦予了介面引數.我用ServiceKnownType裝飾了服務介面,用常規的KnownType裝飾了服務實現,並用常規的KnownType裝飾了datacontract實現:

[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallbacks))]
[ServiceKnownType(typeof(Batch<object>))]
[ServiceKnownType(typeof(Command))]
public interface IActions
{
    [OperationContract]
    IResponse TakeAction(IBatch<ICommand> commands);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant)]
[KnownType(typeof(Batch<object>))]
[KnownType(typeof(Command))]
internal class Actions : IActions
{
}
[DataContract]
[KnownType(typeof(Command))]
public class Batch<T> : IBatch<T>
{
}

出於記錄目的,我在那裏有Batch,因為似乎您只能為一个通用型別表達一个已知型別-它似乎發出BatchOfanyType,但是我不確定如何處理。

我得到的異常是"將任何靜態未知的型別添加到已知型別的列表中-例如,通過使用KnownTypeAttribute屬性或將它们添加到傳遞给DataContractSerializer的已知型別的列表中。"

有什麼明顯的地方我做錯了吗? 是否仅不支援介面的通用介面? 作為記錄,我在该專案的C#2.0和.NET 3.0中。

最新回復
  • 13天前
    1 #

    如果確實愿意,可以在服務合同定義中使用介面,只要您包括以下已知型別: 您正在做(稍作調整,請參见下文).

    顯然,使用介面作為泛型型別引數会使它成為C#3.0的桥梁.我將已知的type屬性更改為

    [ServiceKnownType(typeof(Batch<Command>))]
    public interface IActions
    {
    }
    

    在某種程度上使其起作用.序列化和反序列化本身將起作用,但隨後您將遇到以下異常:

    威兹威兹

    要使该強製轉換正常工作,您需要對通用型別協方差的語言支援,這是C#4.0中引入的.為了使其在C#4.0中工作,您需要添加一个方差修飾符:

    Unable to cast object of type 'Batch`1[Command]' to type 'IBatch`1[ICommand]'.

    然後它可以完美執行...不幸的是,您没有使用C#4.0。

    關於在服務合同中使用介面的最後一件事:如果要从介面生成服務引用,它將把所有介面引數键入為 public interface IBatch<out T> { } ,因為原始介面型別不是元資料的一部分.您可以通過程式集引用共享合同,也可以手動重構生成的代理以對其进行修複,但是总而言之,將介面与wCF一起使用可能比其value更大。

  • 13天前
    2 #

    wCF是SOA訊息, 基於系統的系統-它可以以XML模式表示的序列化XML格式通過網路發送任何內容。

    不幸的是,XML模式既不知道介面,也不知道泛型,所以不知道-您不能通用地序列化這些-需要使用具體型別。

  • 13天前
    3 #

    您不能序列化介面.介面仅定義合同,而不是物件.我猜這是ISerializable介面的一个例外。

  • 13天前
    4 #

    泛型可以序列化,但是有一定的限製.例如,给定資料合同:

    object
    

    以及服務合同:

    [DataContract]
    public class Foo<T>
    {
         [DataMember]
         public T Value { get; set; }
    }
    

    以及服務實現:

    [ServiceContract]
    public interface IService1
    {
         [OperationContract]
         Foo<String> GetData();
    }
    

    在為上述服務設置了服務引用之後,可以執行以下代碼:

    public class Service1 : IService1
    {
       public Foo<string> GetData()
       {
           return new Foo<string>() { Value = "My test string" };
       }
    }
    

    並顯示帶有"我的測試字元串"的訊息框。

    請註意,服務本身不是通用的,但是使用的資料協定是通用的.此外,在客戶端生成的資料協定不是通用的,而是具有字元串型別的屬性值的"扁平化"類:

    ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
    ServiceReference1.FooOfstring temp = client.GetData();
    MessageBox.Show(temp.Value);
    
    [System.Runtime.Serialization.DataMemberAttribute()] public string Value { get {...} set {...} }

  • c#:如何从较小的可重用查詢組成Entity Framework查詢?
  • 使用遗傳演算法的圖像處理