代码之家  ›  专栏  ›  技术社区  ›  ChrisN

使用与WCF的接口

  •  3
  • ChrisN  · 技术社区  · 14 年前

    我已经搜索和阅读了几个小时了,我找不到任何人来处理我的具体情况…

    我想在我的WCF服务契约中使用接口,从线的每一端使用的类中松散地耦合服务。这将使我们能够拥有一个低级的程序集,它只包含我们可以提交给顾问的服务和数据合同(仅包括接口)。在连接的最后,他们可以实例化实现我们的数据契约接口的数据类,通过连接将其发送给我们,然后我们的WCF服务将把输入的数据转换成 我们的 实现相同接口的数据类的版本。

    这是一个例子。 IDataContract 包含我要通过导线传输的裸信息。端点和其他特定于WCF的配置都是默认配置(我的问题可能在于此,所以如果需要更改的话,我可以包含更多配置)。

    编辑 :我已经包含了更多的代码,并重命名了几个类,以帮助它减少混淆。添加到DataContractAttributes的名称和命名空间以及配置文件中的两个部分是基于来自 this blog post . 如果我切换到抽象基类而不是接口, 它工作 . 但是,如果可能的话,我想让它与一个接口一起工作。

    共享库(我的代码,与客户端作者共享):

    public interface IDataContract
    {
        string MyProperty { get; set; }
    }
    [ServiceContract]
    public interface ITestService
    {
        [OperationContract]
        IDataContract TestSharedInterface(IDataContract clientData);
    }
    

    客户代码:

    [DataContract(Name = "IDataContract", Namespace = "http://services.sliderhouserules.com")]
    public class ClientDataClass : IDataContract
    {
        [DataMember]
        public string MyProperty { get; set; }
    }
    private static void CallTestSharedInterface()
    {
        EndpointAddress address = new EndpointAddress("http://localhost/ServiceContractsTest.WcfService/TestService.svc");
        ChannelFactory<ITestService> factory = new ChannelFactory<ITestService>("ITestService", address);
        ITestService proxy = factory.CreateChannel();
        ((IClientChannel)proxy).Open();
    
        IDataContract clientData = new ClientDataClass() { MyProperty = "client data" };
        IDataContract serverData = proxy.TestSharedInterface(clientData);
        MessageBox.Show(serverData.MyProperty);
    }
    

    客户端配置:

    <system.runtime.serialization>
        <dataContractSerializer>
            <declaredTypes>
                <add type="ServiceContractsTest.Contracts.DataContracts.IDataContract, ServiceContractsTest.Contracts">
                    <knownType type="ServiceContractsTest.WcfClient.ClientDataClass, ServiceContractsTest.WcfClient"/>
                </add>
            </declaredTypes>
        </dataContractSerializer>
    </system.runtime.serialization>
    

    服务器代码(我的):

    public class TestService : ITestService
    {
        public IDataContract TestSharedInterface(IDataContract clientData)
        {
            ServerDataClass convertedClientData = (ServerDataClass)clientData;
            IDataContract serverData = new ServerDataClass() { MyProperty = convertedClientData.MyProperty + " + server data added" };
            return serverData;
        }
    }
    [DataContract(Name = "IDataContract", Namespace = "http://services.sliderhouserules.com")]
    public class ServerDataClass : IDataContract
    {
        [DataMember]
        public string MyProperty { get; set; }
    }
    

    服务器配置:

    <system.runtime.serialization>
        <dataContractSerializer>
            <declaredTypes>
                <add type="ServiceContractsTest.Contracts.DataContracts.IDataContract, ServiceContractsTest.Contracts">
                    <knownType type="ServiceContractsTest.WcfService.ServerDataClass, ServiceContractsTest.WcfService"/>
                </add>
            </declaredTypes>
        </dataContractSerializer>
    </system.runtime.serialization>
    

    我在客户端调用上收到一个串行化错误,抱怨已知类型。我只是在那个客户机类中缺少一些元数据标记吗?在我尝试了所有我能想到的搜索之后,我对在哪里知道问题甚至是谎言感到茫然,似乎没有人处理过这个特定的场景。

    基本上,我想要 ClientDataClass 序列化 <IDataContract><MyProperty>client data</MyProperty></IDataContract> 然后能够将其反序列化为 ServerDataClass 实例。这似乎是可能的。

    3 回复  |  直到 12 年前
        1
  •  3
  •   Maurice    14 年前

        2
  •  2
  •   LEitZ    13 年前

    namespace ExampleNamespace
    {
      public interface IJustAInstance { }
    
      [ServiceContract]
      [ServiceKnownType("GetKnownTypes", typeof(ExampleNamespace.TypesHelper))]
      public interface ICreateInstance
      {
        IJustAInstance CreateInstance();
      }
    
      public static class TypesHelper
      {
        public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
        {
          DataContractSerializerSection section = (DataContractSerializerSection)
            ConfigurationManager.GetSection(
            "system.runtime.serialization/dataContractSerializer");
          if (dataContractSerializerSection != null)
          {
            foreach (DeclaredTypeElement item in dataContractSerializerSection.DeclaredTypes)
            {
              foreach (TypeElement innterItem in item.KnownTypes)
              {
                Type type = Type.GetType(innterItem.Type);
                if (typeof(IJustAInstance).IsAssignableFrom(type ))
                  yield return type;
              }
            }
          }
        }
      }
    }
    
        3
  •  0
  •   flayn    14 年前