还有比从 C# 移植到 Java 更好的选择吗?
我有一个用 C# 编写的现有库,它包装了一个低级别的 TCP/IP API,并将来自服务器(专有二进制协议)的消息公开为 .NET 事件。我还提供了对对象的方法调用,该对象处理将方便的 .NET 类型(如 System.DateTime)编组到 API 所需的二进制编码和固定长度结构(用于将消息发送到服务器)的复杂性。有相当多的现有应用程序(包括内部应用程序和第三方使用的应用程序)构建在这个 .NET 库之上。
最近,有人联系我们,他不想自己完成抽象 TCP/IP 的所有跑腿工作,但他们的环境严格非 Windows(我假设是 *nix,但我不是 100% 确定) ,并且他们暗示他们的理想是可以从 Java 调用的东西。
支持他们的需求的最佳方式是什么,而我不必:
- 现在将代码移植到 Java(包括我们当前 P/Invoke 进行解压缩的非托管 DLL)
- 必须维护两个单独的代码库(即制作相同的代码库)错误修复和功能增强两次)
我考虑过的一件事是将大部分核心 TCP/IP 功能重写为跨平台的内容(C / C++),然后将我的 .NET 库更改为一个精简的库层在上面(P/Invoke?),然后在其上编写一个类似的薄 Java 层(JNI?)。
优点:
- 我大部分时间只写一次东西。
缺点:
- 现在大多数代码都是不受管理的——这不是世界末日,但从生产力的角度来看(对我来说)并不理想。
- 开发时间较长(无法像移植到 Java 那样快速地将 C# 套接字代码移植到 C/C++) [这有多真实?]
- 此时,底层 API 大部分已包装并且库非常稳定,因此可能有没有太多新的开发 - 将当前代码移植到 Java,然后必须偶尔进行错误修复或在将来两次公开新字段,这可能并没有那么糟糕。
- 当我现有的客户端应用程序运行的版本在其下面发生巨大变化时,它们可能会不稳定。 (我突然想到了 32/64 位问题、字节顺序问题以及移植过程中可能出现的一般错误等。)
我简要考虑过的另一个选择是以某种方式将 Mono 连接到 Java,所以我可以利用我已有的所有现有 C# 代码。不过,对于必须使用它的 Java 开发人员来说,我不太清楚开发人员的体验有多流畅。我非常确定大多数代码在 Mono 下应该可以毫无问题地运行(除了解压 P/Invoke,无论如何它可能应该移植到 C#)。
理想情况下,如果我可以帮助的话,我不想在我的代码和客户端 Java 应用程序之间添加另一层 TCP/IP、管道等(因此 WCF 到 Java 端 WS-DeathStar 可能已经过时了)。我从未使用 Java 进行过任何认真的开发,但令我感到自豪的是,该库目前对于第三方开发人员来说集成到他的应用程序中是小菜一碟(当然,只要他运行 .NET 即可: )),并且我希望能够为任何想要相同体验的 Java 开发人员保持同样的易用性。
因此,如果有人对我提出的 3 个选项有意见(移植到 Java 并维护两次、移植到 C 并为 .NET 和 Java 编写精简语言绑定,或者尝试集成 Java 和 Mono),或者我提出的任何其他建议很想听听他们的声音。
谢谢
编辑:在直接与客户的开发人员交谈(即拆除损坏的电话又名销售部门)后,要求已经发生了足够的变化,以至于这个问题不再适用于我的当前情况。不过,我将保留这个问题,希望我们能够提出一些更好的建议。
在我的特定情况下,除了 Solaris 之外,客户端实际上还运行 Windows 机器(现在谁不运行?),并且很高兴我们在库之上编写应用程序(Windows 服务)并提供更简化和更小的应用程序TCP/IP API 供他们进行编码。我们将它们的简单消息转换为下游系统可以理解的格式,并将传入的响应转换回供它们使用,以便它们可以继续通过 Java 应用程序与下游系统进行交互。
在考虑了几周之后回到最初的场景,我确实还有一些评论:
如果您了解的话,顶部具有不同语言绑定的可移植的基于 C 的库可能是正确的选择前面您需要支持多种语言/平台。
在 *nix 上,单个进程可以同时托管 Java 运行时和 Mono 运行时吗?我知道在早期版本的 .NET 中,同一进程中不能有两个不同的 .NET 运行时,但我相信他们已经用 .NET 4 修复了这个问题?如果这是可能的,两者之间如何沟通?理想情况下,您需要像静态方法调用和委托这样简单的东西来引发响应。
如果 Java 和 Java 之间没有简单的直接接口支持, Mono(方法和委托等),人们可能会考虑使用带有 Protocol Buffers 的 ZeroMQ 或 Apache Thrift 作为消息格式。 这可以在进程内、进程间和网络上工作。
I have an existing library written in C# which wraps a much lower-level TCP/IP API and exposes messages coming down the wire from a server (proprietary binary protocol) as .NET events. I also provide method calls on an object which handles the complexities of marshalling convenient .NET types (like System.DateTime) down to the binary encodings and fixed-length structures that the API requires (for outgoing messages to the server). There are a fair number of existing applications (both internally and used by third parties) built on top of this .NET library.
Recently, we've been approached by someone who doesn't want to do all the legwork of abstracting the TCP/IP themselves, but their environment is strictly non-Windows (I assume *nix, but I'm not 100% sure), and they've intimated that their ideal would be something callable from Java.
What's the best way to support their requirements, without me having to:
- Port the code to Java now (including an unmanaged DLL that we currently P/Invoke into for decompression)
- Have to maintain two separate code-bases going forwards (i.e. making the same bug-fixes and feature enhancements twice)
One thing I've considered is to re-write most of the core TCP/IP functionality once into something more cross-platform (C / C++) and then change my .NET library to be a thin layer on top of this (P/Invoke?), and then write a similarly thin Java layer on top of it too (JNI?).
Pros:
- I mostly spend my time writing things only once.
Cons:
- Most of the code would now be unmanaged - not the end of the world, but not ideal from a productivity point of view (for me).
- Longer development time (can't port C# sockets code to C / C++ as quickly as just porting to Java) [How true is this?]
- At this point, the underlying API is mostly wrapped and the library is very stable, so there's probably not a lot of new development - it might not be that bad to just port the current code to Java and then have to make occasional bug-fixes or expose new fields twice in the future.
- Potential instability for my existing client applications while the version they're running on changes drastically underneath them. (Off the top of my head I can think of 32/64 bit issues, endianness issues, and general bugs that may crop up during the port, etc.)
Another option I've briefly considered is somehow rigging Mono up to Java, so that I can leverage all of the existing C# code I already have. I'm not too clued up though on how smooth the developer experience will be for the Java developers who have to consume it though. I'm pretty sure that most of the code should run without trouble under Mono (bar the decompression P/Invoke which should probably just be ported to C# anyway).
I'd ideally not like to add another layer of TCP/IP, pipes, etc. between my code and the client Java app if I can help it (so WCF to Java-side WS-DeathStar is probably out). I've never done any serious development with Java, but I take some pride in the fact that the library is currently a piece of cake for a third-party developer to integrate into his application (as long as he's running .NET of course :)), and I'd like to be able to keep that same ease-of-use for any Java developers who want the same experience.
So if anyone has opinions on the 3 options I've proposed (port to Java & maintain twice, port to C and write thin language bindings for .NET and Java or, try and integrate Java and Mono), or any other suggestions I'd love to hear them.
Thanks
Edit: After speaking directly with the developer at the client (i.e. removal of broken telephone AKA Sales Department) the requirements have changed enough that this question no longer applies very well to my immediate situation. However, I'll leave the question open in the hopes that we can generate some more good suggestions.
In my particular case, the client actually runs Windows machines in addition to Solaris (who doesn't these days?) and is happy for us to write an application (Windows Service) on top of the library and provide a much more simplified and smaller TCP/IP API for them to code against. We will translate their simple messages into the format that the downstream system understands, and translate incoming responses back for them to consume, so that they can continue to interface with this downstream system via their Java application.
Getting back to the original scenario after thinking about this for a couple of weeks, I do have a few more comments:
A portable C-based library with different language bindings on top would probably be the way to go if you knew up front that you'd need to support multiple languages / platforms.
On *nix, can a single process host both a Java runtime and a Mono runtime simultaneously? I know in earlier versions of .NET you couldn't have two different .NET runtimes in the same process, but I believe they've fixed this with .NET 4? If this is possible, how would one communicate between the two? Ideally you'd want something as simple as a static method call and a delegate to raise responses with.
If there's no easy direct interface support between Java & Mono (methods & delegates, etc.), one might consider using something like ZeroMQ with Protocol Buffers or Apache Thrift as the message format. This would work in-process, inter-process and over the network because of ZeroMQ's support for different transports.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在决定实施之前,花更多时间确定需求。在您知道需要什么之前,您没有任何选择设计的标准。
例如,如果它是非 Windows 环境,那么在其中的任何位置使用 .NET 就没有意义。
Spend more time getting the requirements nailed down before deciding on an implementation. Until you know what is required, you don't have any criteria for choosing between designs.
If it's a non-windows environment, it doesn't make sense to have .NET anywhere in there, for example.
如果您需要在 Java 虚拟机上运行但看起来很像 C# 的东西,您应该查看 刺伤。这不会对您使用 P/Invoke 等有帮助,但您可能会发现将 C# 代码移植到 Java 并进行维护会减少工作量。
不过,您应该查看 Mono 。我希望所有 C# 代码都可以不经修改地运行(除了接触非托管 DLL 的部分)。
我还没有使用过它,但是 jni4net 应该允许从 Java 调用 .NET 代码。如果您的客户需要 Java 接口,这可能是一个解决方案。
即使 .NET 兼容性不是优先事项,我也一直在 Linux 和 Mac 上使用 Mono。我喜欢 C# 和 .NET 库,并且相比 JVM 更喜欢 CLR。 Mono 已获得 MIT/X11 许可,这意味着您可以根据需要将其用于商业用途。与其他一些人不同,我认为没有理由回避 Microsoft 所倡导的技术,同时青睐 Oracle 和 IBM 所倡导的技术。
尽管您仍然可以 P/Invoke 到本机 DLL,但使用 Mono 不会帮助您处理非托管位。您只需要自己移植该 DLL 或找到一些等效的即可。
您可能还想了解 Mono 提前编译。
If you need something that runs on the Java Virtual Machine but looks a lot like C#, you should check out Stab. This will not help you with P/Invoke and the like but you may find it less work to port your C# code to Java and maintain it.
You should look into Mono though. I expect that all your C# code would run unmodified (except the parts that touch the unmanaged DLL).
I have not used it but jni4net is supposed to allow calling .NET code from Java. If your clients want a Java interface, this may be a solution.
I use Mono on Linux and the Mac all the time even when .NET compatibility is not a priority. I like C# and the .NET libraries and prefer the CLR to the JVM. Mono is MIT/X11 licensed which means that you can use it commercially if you like. Unlike some others, I see no reason to avoid technology championed by Microsoft while favouring technology championed by Oracle and IBM.
Using Mono will not help you with the unmanaged bits, although you can still P/Invoke into a native DLL. You will just have to port that DLL yourself or find some equivalent.
You may also want to look into Mono Ahead of Time compilation.
你考虑过单声道吗?它很可能支持非 Windows 环境中的现有代码。诀窍是从 java 调用它,但是单声道用户也可能有一些东西可以帮助你。
Have you considered mono? It would most likely support your existing code in the non-windows environment. The trick would be calling it from java, but the mono folks might have something to help you out there, too.
对于您的情况,这可能不是正确的解决方案,但为了完整性:
有几种语言可以同时针对 JVM 和 .NET,特别是 Ruby(JRuby 和 IronRuby)和 Python(Jython 和 IronPython)。 Scala 最终也可能实现这一目标,尽管目前 .NET 版本远远落后于 JVM 版本。
不管怎样,您可以用 Ruby 或 Python 重写您的库并针对这两个运行时。
This probably isn't the right solution in your case, but for completeness:
There are a few languages that can target both the JVM and .NET, in particular Ruby (JRuby and IronRuby) and Python (Jython and IronPython). Scala might eventually get there too, although right now the .NET version is a long way behind the JVM version.
Anyway, you could potentially rewrite your library in Ruby or Python and target both runtimes.
如果您真正想要的是能够在 .NET 中编写代码并使其在 JVM 上运行,您可以 查看 Grasshopper(2015-09:链接可能已失效)。这就是它的设计目的。
我知道 Mainsoft 的人多年来一直是 Mono 的贡献者。如果我没记错的话,他们为 Mono 编写了 Visual Basic 编译器。
还有 Tangible 的 C# 到 Java 转换器。我听说过好东西,但我自己从未使用过。
另外,它对你的情况没有多大帮助,但我应该指出Mono for Android。
Mono for Android 并行运行 CLR 和 Dalvik VM。换句话说,您为 Android 编写的 C# 代码可以调用 Java 库(例如 Android UI)并作为单个应用程序执行。您曾询问过在同一进程中运行 .NET 和 Java 代码的能力。显然,这是可以做到的。
If what you really, really want is to be able to code in .NET and have it run on the JVM, you could check out Grasshopper (2015-09: link possibly dead). That is what it is designed to do.
I know the Mainsoft guys have been contributors to Mono over the years. If I remember correctly, they wrote the Visual Basic compiler for Mono.
There is also the C# to Java converter from Tangible. I have heard good things but I have never used it myself.
Also, it does not help your situation much but I should point out Mono for Android.
Mono for Android runs the CLR and the Dalvik VM in parallel. In other words, the C# code you wrote for Android can be calling into Java libraries (like the Android UI for example) and executing as a single app. You had asked about the ability to run .NET and Java code in the same process. Clearly, it can be done.
这是有可能的。在Java方面,您应该考虑使用JNA而不是JNI。 (如果使用 JNI,则需要编写 C/C++ 代码才能使用 JNI 特定的签名。)
另一种可能性是用“只适用于”多种编程语言的协议来替换专有的二进制协议。对于此类问题,CORBA 和类似技术提供了很好的解决方案。
That's a possibility. On the Java side, you should consider using JNA rather than JNI. (If you use JNI, the C / C++ code needs to be written to use JNI-specific signatures.)
Another possibility is to replace the proprietary binary protocol with something that "just works" with multiple programming languages. This is the kind of problem space where CORBA and similar technologies provide a good solution.