WCF开发(9) Unity连接WCF

8 篇文章 0 订阅

参考:https://www.cnblogs.com/JLZT1223/p/6062613.html

和一般连接WCF的不同之处:

1.要手动添加必要的dll

2.要手动创建客户端代码(用svcutil.exe)



我用D盘的绝对路径是因为不加路径会导致无法创建文件,以管理员方式启动cmd的话应该就没问题。

System.Runtime.Serialization.dll不用添加,添加了会说已经存在。我的Unity是5.6.03f

生成文件内容:

//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:2.0.50727.8825
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------



[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="WCFServiceLib", ConfigurationName="ICommonService")]
public interface ICommonService {
    
    [System.ServiceModel.OperationContractAttribute(Action="WCFServiceLib/ICommonService/Hello", ReplyAction="WCFServiceLib/ICommonService/HelloResponse")]
    string Hello(string name);
    
    [System.ServiceModel.OperationContractAttribute(Action="WCFServiceLib/ICommonService/GetString", ReplyAction="WCFServiceLib/ICommonService/GetStringResponse")]
    string GetString(int count, string item);
    
    [System.ServiceModel.OperationContractAttribute(Action="WCFServiceLib/ICommonService/SendString", ReplyAction="WCFServiceLib/ICommonService/SendStringResponse")]
    string SendString(string msg);
    
    [System.ServiceModel.OperationContractAttribute(Action="WCFServiceLib/ICommonService/GetData", ReplyAction="WCFServiceLib/ICommonService/GetDataResponse")]
    WCFModels.DataInfo GetData(string id, string name);
    
    [System.ServiceModel.OperationContractAttribute(Action="WCFServiceLib/ICommonService/SendData", ReplyAction="WCFServiceLib/ICommonService/SendDataResponse")]
    string SendData(WCFModels.DataInfo data);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface ICommonServiceChannel : ICommonService, System.ServiceModel.IClientChannel {
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class CommonServiceClient : System.ServiceModel.ClientBase<ICommonService>, ICommonService {
    
    public CommonServiceClient() {
    }
    
    public CommonServiceClient(string endpointConfigurationName) : 
            base(endpointConfigurationName) {
    }
    
    public CommonServiceClient(string endpointConfigurationName, string remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }
    
    public CommonServiceClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(endpointConfigurationName, remoteAddress) {
    }
    
    public CommonServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
            base(binding, remoteAddress) {
    }
    
    public string Hello(string name) {
        return base.Channel.Hello(name);
    }
    
    public string GetString(int count, string item) {
        return base.Channel.GetString(count, item);
    }
    
    public string SendString(string msg) {
        return base.Channel.SendString(msg);
    }
    
    public WCFModels.DataInfo GetData(string id, string name) {
        return base.Channel.GetData(id, name);
    }
    
    public string SendData(WCFModels.DataInfo data) {
        return base.Channel.SendData(data);
    }
}
namespace WCFModels {
    using System.Runtime.Serialization;
    
    
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.DataContractAttribute(Name="DataInfo", Namespace="http://schemas.datacontract.org/2004/07/WCFModels")]
    public partial class DataInfo : object, System.Runtime.Serialization.IExtensibleDataObject {
        
        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
        
        private string IdField;
        
        private string NameField;
        
        private string TextField;
        
        public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
            get {
                return this.extensionDataField;
            }
            set {
                this.extensionDataField = value;
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public string Id {
            get {
                return this.IdField;
            }
            set {
                this.IdField = value;
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public string Name {
            get {
                return this.NameField;
            }
            set {
                this.NameField = value;
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public string Text {
            get {
                return this.TextField;
            }
            set {
                this.TextField = value;
            }
        }
    }
}

脚本中测试

    private void TestCommonServiceClient()
    {
          CommonServiceClient client = GetCommonServiceClient(WCFClient.Instance.Ip);
          client.SendString("CommonServiceClient Start");
          WCFModels.DataInfo data = client.GetData("1", "2");
          Write(string.Format("{0},{1}", data.Id, data.Name));
    }

    public static CommonServiceClient GetCommonServiceClient(string ip)
    {
        NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
        binding.MaxReceivedMessageSize = int.MaxValue;
        EndpointAddress endpointAddress = new EndpointAddress("net.tcp://" + ip + ":8001/CommonService");
        CommonServiceClient currentClient = new CommonServiceClient(binding, endpointAddress);
        return currentClient;
    }
可以

接下来试试这部分代码在Hololens中能不能正常运行。

当初的最终目标就是在Hololens中使用wcf的,因为Hololens的运行环境是UWP,所以先研究了在UWP中使用WCF,然后再通过接口的方式在脚本中使用。

这么看来可能不需要这样。

等待后续测试吧,说不定在Hololens中不能使用呢。

=======================================================

svcutil生成的代码中的 数据类型 和 Unity引用的dll中的数据类型重复了,必须手动删除那部分代码。想让svcutil只生成客户代码,添加-reference:参数,没用,还是会生成。

用VS生成的话,只要客户端项目引用了数据类型所在的dll就不会重新创建这些类型的代码了了。

但是用VS添加服务引用生成的代码中包含异步调用的代码...

将客户端项目修改为3.5的(原本是4.5的),异步调用代码就没有了。

不使用svcutil.exe,还是用VS 项目生成代码吧,再移动到Unity中好了。
==========================================================

考虑到异步处理,还是用回调函数的方式处理返回结果,做一个Unity版本的WCFClient

将UWP中的代码移动到Unity中,相应的修改代码(基本上去掉async和await就行了),语法没问题,测试。

问题1:

获取列表数据时数量没问题,但是无法获取具体数据内容。发现是因为数据类中没有添加DataContract和DataMember,但是用UWP的话可以,之前有测试过的,没加相当于全加上的,但是这样看来在这里不适用。加上合适的DataContract和DataMember就可以了,加[Serializable]没用(《WCF服务编程》里面是说可以的)。

问题2:

MainTest:System.Xml.XmlException: Text content buffer exceeds the quota limitation at 5339. 12220 bytes and should be less than 8192 bytes
  at System.Xml.XmlBinaryDictionaryReader.Alloc (Int32 size) [0x00000] in <filename unknown>:0 
  at System.Xml.XmlBinaryDictionaryReader.ReadTextOrValue (Byte ident, System.Xml.NodeInfo node, Boolean canSkip) [0x00000] in <filename unknown>:0 
  at System.Xml.XmlBinaryDictionaryReader.Read () [0x00000] in <filename unknown>:0 
  at System.Xml.XmlReader.Skip () [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer, Boolean empty) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeObject (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializeByMap (System.Xml.XmlQualifiedName name, System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializeCore (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.CollectionTypeMap.DeserializeContent (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.SerializationMap.DeserializeObject (System.Xml.XmlReader reader, System.Runtime.Serialization.XmlFormatterDeserializer deserializer) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializeByMap (System.Xml.XmlQualifiedName name, System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.DeserializeCore (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Type type, System.Xml.XmlReader reader) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlFormatterDeserializer.Deserialize (System.Xml.XmlReader reader, System.Type type, System.Runtime.Serialization.KnownTypeCollection knownTypes, IDataContractSurrogate surrogate, System.String name, System.String ns, Boolean verifyObjectName) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.DataContractSerializer.ReadObject (System.Xml.XmlDictionaryReader reader, Boolean verifyObjectName) [0x00000] in <filename unknown>:0 
  at System.Runtime.Serialization.XmlObjectSerializer.ReadObject (System.Xml.XmlDictionaryReader reader) [0x00000] in <filename unknown>:0 
  at System.ServiceModel.Dispatcher.DataContractMessagesFormatter.MessageToParts (System.ServiceModel.Description.MessageDescription md, System.ServiceModel.Channels.Message message) [0x00000] in <filename unknown>:0 
  at System.ServiceModel.Dispatcher.BaseMessagesFormatter.DeserializeReply (System.ServiceModel.Channels.Message message, System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at System.ServiceModel.ClientRuntimeChannel.Request (System.ServiceModel.Description.OperationDescription od, System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at System.ServiceModel.ClientRuntimeChannel.DoProcess (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters) [0x00000] in <filename unknown>:0 
  at System.ServiceModel.ClientRuntimeChannel.Process (System.Reflection.MethodBase method, System.String operationName, System.Object[] parameters) [0x00000] in <filename unknown>:0 
UnityEngine.Debug:Log(Object)
应该是反序列化时数据量太大了。是因为有一个字符串属性的字符串内容长度为12220导致的。

两个都是反序列化的问题,一般来说是没问题的(正常添加DataContract,一个字符串属性长度不要太大)。

结论:可以使用。

=====================================================================

打包成Hololens的SLN时有问题,

 1. System.ServiceModel.dll重复了,说是已经存在了。修改dll的设置,WSAPlayer不选,只在Unity中使用。


 2. 前面生成的客户端代码不能用,特性相关的dll不能使用。修改代码,整个WCF客户端代码文件用#if UNITY_EDITOR包起来,只在Unity中测试用。

虽然在Hololens中无法使用,但是不如说正好接上UWP中的版本,一个用于在Unity中测试,测试好后再打包到UWP中测试,能显著减少打包成UWP的次数。


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值