参考:https://www.cnblogs.com/JLZT1223/p/6062613.html
和一般连接WCF的不同之处:
1.要手动添加必要的dll
2.要手动创建客户端代码(用svcutil.exe)
我用D盘的绝对路径是因为不加路径会导致无法创建文件,以管理员方式启动cmd的话应该就没问题。
System.Runtime.Serialization.dll不用添加,添加了会说已经存在。我的Unity是5.6.03f
生成文件内容:
//------------------------------------------------------------------------------
脚本中测试
//
// 此代码由工具生成。
// 运行时版本:2.0.50727.8825
//
// 对此文件的更改可能会导致不正确的行为,并且如果
// 重新生成代码,这些更改将会丢失。
//
//------------------------------------------------------------------------------[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
}
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 bytesat System.Xml.XmlBinaryDictionaryReader.Alloc (Int32 size) [0x00000] in
应该是反序列化时数据量太大了。是因为有一个字符串属性的字符串内容长度为12220导致的。
UnityEngine.Debug:Log(Object)
两个都是反序列化的问题,一般来说是没问题的(正常添加DataContract,一个字符串属性长度不要太大)。
结论:可以使用。
=====================================================================
打包成Hololens的SLN时有问题,
1. System.ServiceModel.dll重复了,说是已经存在了。修改dll的设置,WSAPlayer不选,只在Unity中使用。
2. 前面生成的客户端代码不能用,特性相关的dll不能使用。修改代码,整个WCF客户端代码文件用#if UNITY_EDITOR包起来,只在Unity中测试用。
虽然在Hololens中无法使用,但是不如说正好接上UWP中的版本,一个用于在Unity中测试,测试好后再打包到UWP中测试,能显著减少打包成UWP的次数。