上下文
我使用本教程构建了一个非常基本的WCF服务器和客户端,并试图让它在iOS设备上运行。我能够在Unity和XCode中构建应用程序,并且能够在编辑器中连接到服务器。但是,当我实际尝试将客户端连接到服务器时,我得到了一个空引用异常。
堆栈跟踪显示此错误是由System.ServiceModel
类引发的。
NullReferenceException: Object reference not set to an instance of an object
at System.ServiceModel.ChannelFactory`1[TChannel].CreateChannel () [0x00000] in <c9bd1c5fa2104489802ea2feced48e51>:0
at callService.Start () [0x0001a] in C:UsersQADocumentsCodebaseWCFTestAssetsScriptscallService.cs:16
这是我使用Unity安装目录中的svcutil.exe
工具生成的代理类。
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="IService1")]
public interface IService1 {
[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IService1/GetData", ReplyAction="http://tempuri.org/IService1/GetDataResponse")]
string GetData(string name, int value);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public interface IService1Channel : IService1, System.ServiceModel.IClientChannel {
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
public partial class Service1Client : System.ServiceModel.ClientBase<IService1>, IService1 {
public Service1Client() {
}
public Service1Client(string endpointConfigurationName) :
base(endpointConfigurationName) {
}
public Service1Client(string endpointConfigurationName, string remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public Service1Client(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
base(endpointConfigurationName, remoteAddress) {
}
public Service1Client(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress) {
}
public string GetData(string name, int value) {
return base.Channel.GetData(name, value);
}
}
我在网上发现了一些带有相关错误的线程,这些错误给了我一些提示,说明为什么这个System.ServiceModel
库会在运行时抛出NullReferenceException
。包括此页面表明System.ServiceModel
可能引用的一些.NET库与iOS不兼容,因此可能会在构建过程中被剥离。我试了好几种方法,但到目前为止都没有成功。
- 我尝试添加一个链接器文件,以确保
System.ServiceModel
类的某些部分不会被剥离 - 我试过使用不同版本的
System.ServiceModel
。我添加了上的用户共享的库的这些双工版本。我还尝试使用Unity安装路径中的库版本:C:Program FilesUnityHubEditor2020.3.17f1EditorDataMonoBleedingEdgelibmono2.0-api
- 我已经尝试过重写CreateChannels()方法,这通常被认为是必要的,以避免像本文中那样使用动态代码生成的代码
经过多次尝试,从不同的地方使用不同的svcutil
命令和System.ServiceModel
DLL,我发现了这个页面,它指示了System.ServiceModel
的哪个版本与Xamarin.iOS
兼容(我认为它与Unity有类似的兼容性限制)。
由于Windows Phone使用Silverlight并使用Xamarin构建,我使用了System.ServiceModel
和System.XML.Serialization
,它们可以在Windows Phone SDK文件夹中找到:
C:Program Files (x86)Microsoft SDKsWindows Phonev8.0ToolsMDILXAPCompileFramework
为了获得这个文件夹,我不得不从这个网站下载一个旧的.iso版本的Windows Phone sdk,并且我必须使用附近文件夹中的SLSVCutil
可执行文件生成一个新的代理类:
C:Program Files (x86)Microsoft SDKsWindows Phonev8.0Tools
使用silverlight版本的库需要对Unity中的客户端类进行一些小的更改,如下所示:
using System.ServiceModel;
using TMPro;
using UnityEngine;
public class CallService : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI display = null;
void Start()
{
EndpointAddress endpoint = new EndpointAddress("http://192.168.1.15/WcfService/Service1.svc/WcfDemoService");
BasicHttpBinding binding = new BasicHttpBinding();
Service1Client client = new Service1Client(binding, endpoint);
client.GetDataCompleted += PrintToScreen;
client.GetDataAsync("brennan", 10);
}
private void PrintToScreen(object sender, GetDataCompletedEventArgs e)
{
string resultString = e.Result;
Debug.LogWarning(resultString);
display.text = resultString;
}
}