C#到Java 的转换 – 在 Java 环境中使用 .NET Framework 逻辑

将某些项目从一种语言翻译为另一种语言不仅涉及源代码更改,还涉及我们执行该项目的环境。CodePorting.Translator Java Class Library 确实通过 JCL (Java class library) 实现了这样的环境,保留了.NET Framework类库的逻辑和结构,这使得翻译的项目感觉宾至如归,将其隐藏在Java平台实现之外。

CodePorting.Translator Java Class Library

JCL(Java Class Library)在通用设计、异常处理和逻辑方面与 .NET 类库存在差异。因此,如果我们决定将代码从 C# 转换到 Java,仅仅替换类和函数的名称是不安全的。有一种解决方案可以生成包装代码,重现 .NET Framework 类库的逻辑。但这样一来,生成的 Java 代码将与原始 C# 代码大相径庭,这并不是我们所期望的 – 我们希望翻译器保持原始程序结构。因此,我们有必要实现.NET 框架类库的 Java 替代。

它是如何工作的

让我们从简单的事情开始:

using System;

class Program
{
    public static void Main(string[] args)
    {
        Console.WriteLine("Hello, Example!");
    }
}

我们这里有一个来自 .NET Framework 类库的类 – System.Console
翻译后的 Java 代码看起来如何?

import com.codeporting.ms.System.Console;

class Program
{
    public static void main(String[] args)
    {
        Console.writeLine("Hello, Example!");
    }
}

正如您所看到的,该翻译器确实将 C# System.Console 类的引用替换为 Java com.codeporting.ms.System.Console 类,在CodePorting.Translator Java Class Library中实现。

好吧,现在让我们看另一个例子:

using System;
using System.Collections.Generic;

class Program
{
    public static void Main(string[] args)
    {
        PrintList(new List<string> { "Hello, list!", "I have a list for you to print!" });
    }
    public static void PrintList(List<string> list)
    {
        foreach(var item in list) Console.WriteLine(item);
    }
}

翻译后的 Java 代码如下:

import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Collections.Generic.List;
import com.codeporting.ms.System.Console;
import com.codeporting.ms.System.IDisposable;
import java.util.Iterator;

class Program
{
    public static void main(String[] args)
    {
        List<String> tmp = new List<String>();
        tmp.addItem("Hello, list!");
        tmp.addItem("I have a list for you to print!");
        printList(tmp);
    }
    public static void printList(IGenericEnumerable<String> list)
    {
        //Foreach to while statement conversion
        Iterator<String> variable1 = list.iterator();
        try
        {
            while (variable1.hasNext())
            {
                String item = variable1.next();
                Console.writeLine(item);
            }
        }
        finally
        {
            if (variable1 != null)
            {
                ((IDisposable)variable1).dispose();
            }
        }
    }
}

在这里,我们看到了使用 CodePorting.Translator Java Class Library 的另一个好处 – 我们保持了 C# 抽象之间的关系。System.Collections.Generic.List 实现了 IEnumerable 接口,这使我们能够使用 foreach 循环遍历它。Java 有java.lang.Iterable接口,它看起来与 IEnumerable 类似,但它们在设计上有细微差别,这可能会对大型项目产生决定性影响。

公共 API 纯度

尽管我们有一个很好的库可供使用,但我们翻译的项目确实需要可供客户访问和理解,并且他们可能更喜欢使用 JCL 类。 如果我们使用 CodePorting.Translator Java Class Library,那么对外界来说是一件好事。 而且,这里我们还有另一个有趣的 CodePorting.Translator 功能:ApiChange。 这个功能有什么作用? 它隐藏使用 CodePorting.Translator Java Class Library的方法,创建使用 JCL 类的代理方法。 让我们看一下例子:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Newspaper
{
    public class Article
    {
        public DateTime Published { get; set; }
        public string Content { get; set; }
    }

    public class Archive
    {
        List<Article> articles = new List<Article>();

        public void AddArticle(Article article)
        {
            articles.Add(article);
        }

        public IEnumerable<Article> GetArticlesForPeriod(DateTime start, DateTime end)
        {
            if(start > end || start > DateTime.Now)
            {
                return new Article[0];
            }
            return articles.Where(article => article.Published >= start && article.Published <= end);
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var archive = new Archive();
            archive.AddArticle(
                new Article() {
                    Published = new DateTime(2012, 12, 20), Content = "End of the world comes tomorrow!" });
            archive.AddArticle(
                new Article() {
                    Published = new DateTime(2012, 12, 22), Content = "It was a huge joke..." });
            var articles = archive.GetArticlesForPeriod(
                new DateTime(2000, 1, 1),
                new DateTime(2012, 12, 21));
            foreach(var article in articles)
            {
                Console.WriteLine(article.Content);
            }
        }
    }
}

您可以在这里看到一个简单的类 Archive,它存储了一些文章并提供访问这些文章的功能,根据文章发表的日期进行筛选。 类 System.DateTime.NET Framework 类库的一部分,尽管我们可能会在项目中使用它,但我们希望对外部世界隐藏它:

Article.java

package Newspaper;

import com.codeporting.ms.System.DateTime;
import java.util.Date;

public class Article
{
    private DateTime auto_Published = new DateTime();
    final DateTime getPublishedInternal() { return auto_Published.Clone(); }
    public final Date getPublished() {
        return DateTime.toJava(getPublishedInternal());
    }
    final void setPublishedInternal(DateTime value) { auto_Published = value.Clone(); }
    public final void setPublished(Date value) {
        setPublishedInternal(DateTime.fromJava(value));
    }
    private String auto_Content;
    public final String getContent() { return auto_Content; }
    public final void setContent(String value) { auto_Content = value; }
}

Archive.java

package Newspaper;

import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Collections.Generic.List;
import com.codeporting.ms.System.DateTime;
import com.codeporting.ms.System.Func;
import java.util.Date;

public class Archive
{
    private Archive[] Archive_this = {this};
    private List<Article> articles = new List<Article>();

    public final void addArticle(Article article)
    {
        articles.addItem(article);
    }

    final IGenericEnumerable<Article> getArticlesForPeriodInternal(DateTime start, DateTime end)
    {
        if(DateTime.op_GreaterThan(start, end) || DateTime.op_GreaterThan(start, DateTime.getNow()))
        {
            return com.codeporting.ms.System.Array.<Article>toGenericList(new Article[0]);
        }
        return articles.where(new Func<Article,Boolean>() {
            public String getDelegateId() {
                return System.identityHashCode(Archive_this[0]) + "-89480671";
            }
            public Boolean invoke(Newspaper.Article article) {
                return DateTime.op_GreaterThanOrEqual(article.getPublishedInternal(), start) 
                    && DateTime.op_LessThanOrEqual(article.getPublishedInternal(), end);
            }
        });
    }

    public final java.lang.Iterable<Article> getArticlesForPeriod(Date start, Date end)
    {
        IGenericEnumerable<Article> temp=getArticlesForPeriodInternal(
            DateTime.fromJava(start),
            DateTime.fromJava(end));
        java.util.ArrayList<Article> temp_java=new java.util.ArrayList<Article>();
        {
            com.codeporting.ms.System.Collections.Generic.IGenericEnumerator<Article> temp_iterator=temp.iterator();
            while(temp_iterator.hasNext())
            {
                Article element=temp_iterator.next();
                temp_java.add(element);
            }
        }
        return temp_java;
    }
}

Program.java

package Newspaper;

import com.codeporting.ms.System.Collections.Generic.IGenericEnumerable;
import com.codeporting.ms.System.Console;
import com.codeporting.ms.System.DateTime;
import com.codeporting.ms.System.IDisposable;
import java.util.Iterator;

public class Program
{
    public static void main(String[] args)
    {
        Archive archive = new Archive();
        Article tmp = new Article();
        tmp.setPublishedInternal(new DateTime(2012, 12, 20));
        tmp.setContent("End of the world comes tomorrow!" ) ;
        archive.addArticle(tmp);
        Article tmp_1 = new Article();
        tmp_1.setPublishedInternal(new DateTime(2012, 12, 22));
        tmp_1.setContent("It was a huge joke..." ) ;
        archive.addArticle(tmp_1);
        IGenericEnumerable<Article> articles = archive.getArticlesForPeriodInternal(
	        new DateTime(2000, 1, 1),
	        new DateTime(2012, 12, 21));
        //Foreach to while statement conversion
        Iterator<Article> variable1 = articles.iterator();
        try
        {
            while (variable1.hasNext())
            {
                Article article = variable1.next();
                Console.writeLine(article.getContent());
            }
        }
        finally
        {
            if (variable1 != null)
            {
                ((IDisposable)variable1).dispose();
            }
        }
    }
}

翻译成 Java 的代码无法通过 公共 API 访问 CodePorting.Translator Java Class Library,并且外部 Java 世界可以使用公共代理方法与我们的 Archive 类进行交互。

我们可能得出的结论

CodePorting.Translator Java Class Library 确实提供了一个抽象层和对 JCL 的控制,这分散了我们对实现细节的注意力,并允许我们思考我们解决的问题。 它还有助于保持原始代码的结构,提高翻译结果的理解力和透明度。

相关文章