首页 新闻 会员 周边

WCF 中CollectionMapping的手动添加。

0
悬赏园豆:200 [待解决问题]

NH+WCF

其中NH中一对多的结构为

 

IList<Test> Detail

{

 

}

然后 WCF在客户端

var wsHttp = new BasicHttpBinding(BasicHttpSecurityMode.None);
ChannelFactory<T> channelFactory = new ChannelFactory<T>(wsHttp, "http://" + "localhost:9999" + "/" + url);

但是当客户端调用的时候 去使用 Detail这个属性的时候发现 集合对象变成了【只读】的状态,原因为 生成的 返回对象为IList 但是NH又没有办法做改动,项目中也不能添加服务的引用,请问如何在ChannelFactory 中设置CollectionMappings 属性啊!!

WCF
啤酒草的主页 啤酒草 | 初学一级 | 园豆:2
提问于:2014-01-23 16:06
< >
分享
所有回答(1)
0

你能用代码解释下你的 Detail 如何是只读的?也就是说你为什么说它是只读的?

Launcher | 园豆:45045 (高人七级) | 2014-01-23 16:22

因为在 IList 反序列化回来的时候 IList<T> 实际上被序列化成了  Array<T> 成了一个定长数组,而我又不希望在项目中直接 【引用服务】,所以 无法生成  

<CollectionMappings>
<CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
</CollectionMappings>

的映射。

支持(0) 反对(0) 啤酒草 | 园豆:2 (初学一级) | 2014-01-24 08:36

@啤酒草: 我很好奇的问一句,CollectionMapping 是 NH 中的,还是 WCF 中的?

调用 WCF 服务有两种方式,一种是通过服务引用生成代理类,另一种方式就是手动编写代理类代码。第二种方式你可以参考 StockTrader 中的示例。

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2014-01-24 09:27

@Launcher: CollectionMapping  是WCF中直接应用服务所生生的

<?xml version="1.0" encoding="utf-8"?>
<ReferenceGroup xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="9ab7031e-9d9f-4592-b272-43afcac553e7" xmlns="urn:schemas-microsoft-com:xml-wcfservicemap">
<ClientOptions>
<GenerateAsynchronousMethods>false</GenerateAsynchronousMethods>
<EnableDataBinding>true</EnableDataBinding>
<ExcludedTypes />
<ImportXmlTypes>false</ImportXmlTypes>
<GenerateInternalTypes>false</GenerateInternalTypes>
<GenerateMessageContracts>false</GenerateMessageContracts>
<NamespaceMappings />
<CollectionMappings>
<CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
</CollectionMappings>
<GenerateSerializableTypes>true</GenerateSerializableTypes>
<Serializer>Auto</Serializer>
<ReferenceAllAssemblies>true</ReferenceAllAssemblies>
<ReferencedAssemblies />
<ReferencedDataContractTypes />
<ServiceContractMappings />
</ClientOptions>
<MetadataSources>
<MetadataSource Address="http://localhost:9999/TestService/metadata" Protocol="http" SourceId="1" />
</MetadataSources>
<Metadata>
<MetadataFile FileName="TestService.wsdl" MetadataType="Wsdl" ID="22af1928-583f-4e1b-a7f9-d2876daafac8" SourceId="1" SourceUrl="http://localhost:9999/TestService/metadata" />
<MetadataFile FileName="metadata.xsd" MetadataType="Schema" ID="7c9e6d59-59bb-472e-8493-905661a00eba" SourceId="1" SourceUrl="http://localhost:9999/TestService/metadata?xsd=xsd2" />
<MetadataFile FileName="metadata1.xsd" MetadataType="Schema" ID="88452e87-d36d-4689-ace5-065cbf3e6156" SourceId="1" SourceUrl="http://localhost:9999/TestService/metadata?xsd=xsd1" />
<MetadataFile FileName="metadata2.xsd" MetadataType="Schema" ID="d2d2cd8c-2dc8-4f00-8310-3f2e38760d42" SourceId="1" SourceUrl="http://localhost:9999/TestService/metadata?xsd=xsd0" />
<MetadataFile FileName="metadata.wsdl" MetadataType="Wsdl" ID="ca974723-d890-475c-8654-18a6fc701521" SourceId="1" SourceUrl="http://localhost:9999/TestService/metadata?wsdl=wsdl0" />
</Metadata>
<Extensions>
<ExtensionFile FileName="configuration91.svcinfo" Name="configuration91.svcinfo" />
<ExtensionFile FileName="configuration.svcinfo" Name="configuration.svcinfo" />
</Extensions>
</ReferenceGroup>

 

但是我们的开发环境是不直接应用服务的,所以这个属性不知道哪里去设置

支持(0) 反对(0) 啤酒草 | 园豆:2 (初学一级) | 2014-01-24 09:52

@啤酒草:

1、 “我又不希望在项目中直接 【引用服务】”

2、“是WCF中直接应用服务所生生的” ——你这里可能是笔误,你应该想说的是“是WCF中直接引用服务所生生的”

请问,你到底是想,还是不想“直接引用服务”?

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2014-01-24 10:18

@Launcher: 我不想直接应用服务 我上面没有表述清楚吧,我接着表述一下

ServiceContract:

 [ServiceContract()]
 public interface ITestService
    {
        [OperationContract]
        IList<TestObject> Add();
  }

 Service:

public class TestService :ITestService
{
      public IList<TestObject> Add()
        {
            List<TestObject> list = new List<TestObject>();
            list.Add(new TestObject());
            list.Add(new TestObject());
            list.Add(new TestObject());
            list.Add(new TestObject());
            return list;

        }    
}

TestObject:

[System.Runtime.Serialization.DataContract()]
    public class TestObject
    {
        [System.Runtime.Serialization.DataMember()]
        public string AAA
        {
            get;
            set;
        }
    }

ServiceHost:

    public class ERPServerHost : ServiceHost
    {
      

        public ERPServerHost(Type hostType,Type interFaceType,string serviceName):base(hostType,
            new Uri[]{new Uri(@"http://localhost:9999/TestService/")})
        {


        

            var wsHttp = new BasicHttpBinding(BasicHttpSecurityMode.None);


            this.AddServiceEndpoint(interFaceType, wsHttp, "");
         

         
            if (this.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
            {
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

                behavior.HttpGetEnabled = true;
                behavior.HttpGetUrl = new Uri(@"http://localhost:9999/TestService/"  + "metadata");
                this.Description.Behaviors.Add(behavior);

            }
            ServiceDebugBehavior debug = new ServiceDebugBehavior();
            debug.IncludeExceptionDetailInFaults = true;
            this.Description.Behaviors.Add(debug);
           
            this.Open();

        }
}

客户端有二种生成方式

第一种直接引用服务,然后再类型列表中选择 集合类型为 【List类型】,然后查看生成的代理类,发现XML上多了一段

 <CollectionMappings>
      <CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
    </CollectionMappings>

这个时候 生成的 ITestService接口的是这样的:

[System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
    public partial class TestServiceClient : System.ServiceModel.ClientBase<Client.ServiceReference1.ITestService>, Client.ServiceReference1.ITestService {
        
        public TestServiceClient() {
        }
        
        public TestServiceClient(string endpointConfigurationName) : 
                base(endpointConfigurationName) {
        }
        
        public TestServiceClient(string endpointConfigurationName, string remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }
        
        public TestServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(endpointConfigurationName, remoteAddress) {
        }
        
        public TestServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
                base(binding, remoteAddress) {
        }
        
        public System.Collections.Generic.List<Modal.TestObject> Add() {
            return base.Channel.Add();
        }
    }

返回值为  List<TestObject>

第二种方式为工作创建方法:

  var wsHttp = new BasicHttpBinding(BasicHttpSecurityMode.None);
 ChannelFactory<T> channelFactory = new ChannelFactory<T>(wsHttp, "http://" + "localhost:9999" + "/" + url);
 return channelFactory.CreateChannel();

这个时候创建的接口 返回值 确实 TestObject[] 类型的定长数组。

 

求问:如何 采用工厂创建服务接口的方式  让返回值变为 List<TestObject>,既使用代码将

<CollectionMappings>
      <CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
    </CollectionMappings>

 

 

支持(0) 反对(0) 啤酒草 | 园豆:2 (初学一级) | 2014-01-24 15:16

@啤酒草: ChannelFactory<ITestService> channelFactory = new ChannelFactory<ITestService>()....

直接把服务器的 dll 引用进来使用就行了,完整实现,你可以看下 StockTrader .

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2014-01-24 16:54

@Launcher: 客服端去应用服务器端的DLL文件?好像不是这样的吧。

支持(0) 反对(0) 啤酒草 | 园豆:2 (初学一级) | 2014-01-25 08:40

@啤酒草: 如果你还没有下载 StockTrader 项目学习过,那么请你学习完了后再发表你的结论。如果你都懒得去学习,仅凭感觉就说“好象不是这样吧”,那么我也无法再回答你的问题了。

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2014-01-26 09:12
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册