【问题标题】:What APIs of the .NETStandard are actually implemented in Xamarin.Android?Xamarin.Android 中实际实现了 .NETStandard 的哪些 API?
【发布时间】:2017-02-24 03:44:28
【问题描述】:

如何确定 Xamarin.Android 是否实际实现/支持 .NETStandard API?我有一个在 .NETStandard1.4 库中实现的 WCF net.tcp 客户端。我从 Xamarin.Android 应用程序中引用此库并尝试调用客户端方法。 它编译得很好,但在客户端方法调用上会抛出一个NotImplementedException

难道 Xamarin.Android 没有实现某些 API,但仍然“支持”.NETStandard1.4?我问是因为我找不到任何说它不受支持的东西,我想使用的所有类/方法都记录在 Xamarins 在线文档中(例如https://developer.xamarin.com/api/type/System.ServiceModel.ClientBase%3CTChannel%3E/)并且没有提到“未实现”,但我得到了NotImplementedException。目前我无法判断它是否真的不受支持,或者我的安装/项目是否有问题。

如果是,.NETStandard 库的确切用途是什么,如果有人可以简单地声称支持它并将NotImplementedException 扔在任何东西上?

为了完整性:

Xamarin.Android 应用:

// MainActivity.cs
using Android.App;
using Android.Widget;
using Android.OS;
using System.ServiceModel;

namespace App1
{
    [Activity(Label = "App1", MainLauncher = true, Icon = "@drawable/icon")]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            // SetContentView (Resource.Layout.Main);
            var endpoint = new EndpointAddress("net.tcp://192.168.192.189:8550/iQOSApp_AppService");
            var binding = new NetTcpBinding(SecurityMode.None);
            var client = new iQOSApp.Clients.AppContractClient(binding, endpoint);
            int n = client.GetData(0); // NotImplementedException
        }
    }
}

.NET 标准库:

// Clients.cs
//------------------------------------------------------------------------------
// <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>
//------------------------------------------------------------------------------

namespace iQOSApp.Clients
{


    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    [System.ServiceModel.ServiceContractAttribute(ConfigurationName = "iQOSApp.Clients.IAppContract")]
    public interface IAppContract
    {

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IAppContract/GetData", ReplyAction = "http://tempuri.org/IAppContract/GetDataResponse")]
        int GetData(int value);

        [System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IAppContract/GetData", ReplyAction = "http://tempuri.org/IAppContract/GetDataResponse")]
        System.Threading.Tasks.Task<int> GetDataAsync(int value);
    }

    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public interface IAppContractChannel : iQOSApp.Clients.IAppContract, System.ServiceModel.IClientChannel
    {
    }

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
    public partial class AppContractClient : System.ServiceModel.ClientBase<iQOSApp.Clients.IAppContract>, iQOSApp.Clients.IAppContract
    {

        public AppContractClient()
        {
        }

        public AppContractClient(string endpointConfigurationName) :
                base(endpointConfigurationName)
        {
        }

        public AppContractClient(string endpointConfigurationName, string remoteAddress) :
                base(endpointConfigurationName, remoteAddress)
        {
        }

        public AppContractClient(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
                base(endpointConfigurationName, remoteAddress)
        {
        }

        public AppContractClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
                base(binding, remoteAddress)
        {
        }

        public int GetData(int value)
        {
            return base.Channel.GetData(value);
        }

        public System.Threading.Tasks.Task<int> GetDataAsync(int value)
        {
            return base.Channel.GetDataAsync(value);
        }
    }
}

【问题讨论】:

  • 我忘了说,我用的是VS 2017 RC
  • 您可能会尝试升级到最新的 Cycle 9 版本(今天才可用)以查看此问题是否已修复,但一般而言,Xamarin 平台上的 .NET Standard 支持还不是那么可靠。只有在 .NET Core 2.0 可用时,它才能完全工作。
  • 您能否谈谈一旦 .NET Core 2.0 可用后 Xamarin 将完全支持它的可能性有多大?
  • 如果您确实在 GitHub 上查看 Mono 存储库,您会看到正在填补 .NET Standard 2.0 兼容性的漏洞。当前的 Xamarin.Android/Mono 4.8 仅与 1.6 兼容,而您仍然会看到此类问题。

标签: c# wcf xamarin xamarin.android .net-standard


【解决方案1】:

难道 Xamarin.Android 没有实现某些 API,但仍然“支持”.NETStandard1.4?

是的,这是正确的。事实上,有许多旧平台会在它们没有实现的区域抛出 NIE(未实现异常)。这更像是 Mono 兼容性:http://www.mono-project.com/docs/about-mono/compatibility/

您可以实现自己的平台并在您的实现中抛出PlatformNotSupportedException,这将被视为“支持netstandard”。 Aaron Nurse 对此有很好的见解:https://gist.github.com/davidfowl/8939f305567e1755412d6dc0b8baf1b7#gistcomment-1759645

因此,您很可能遇到 Mono 的 WCF 堆栈缺少某些功能的问题:

http://www.mono-project.com/docs/web/wcf/

通常,Xamarin 平台支持与 Silverlight 运行时一起提供的 WCF 客户端子集。这包括 WCF 最常见的编码和协议实现——使用 BasicHttpBinding 类的 HTTP 传输协议上的文本编码 SOAP 消息。此外,WCF 支持需要使用仅在 Windows 环境中可用的工具来生成代理。

https://developer.xamarin.com/guides/xamarin-forms/web-services/consuming/wcf/

注意:请注意其中某些类型的 Xamarin 文档。它们是直接从 MSDN 中提取的,并不意味着如果它在 BCL 中列出,则支持所有内容。更准确的组装清单请见:

https://developer.xamarin.com/guides/cross-platform/advanced/available-assemblies/

您最好查看 Silverlight MSDN 文档:https://msdn.microsoft.com/en-us/library/system.servicemodel(v=vs.95).aspx

【讨论】:

  • 第一段可能是错误的。许多平台应该抛出PlatformNotSupportedException,如here,而不是NotImplementedException
  • @LexLi 是的,你是对的。我只是试图解释 WRT 单声道的概念:mono-project.com/docs/about-mono/compatibility 我将进行编辑以使其更有意义。
  • 我尝试使用 SlSvcUtil.exe 生成与 Silverlight 兼容的客户端,但抛出了完全相同的异常。不管怎样,你回答了我的问题,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-02
  • 1970-01-01
  • 2018-02-07
相关资源
最近更新 更多