解决 嵌套类

罗伯特·NZ

活跃的成员
已加入
2020年6月26日
留言内容
34
编程经验
Beginner
我需要将COBOL记录布局映射到C#(或VB)类中。 COBOL记录布局可能具有许多定义级别,并且我需要能够应对可能重复字段名称的规则,只要有一种方法可以完全限定您要区分哪个字段。当我发现一个类可以嵌套在另一个类中时,我以为我可以在C#中做同样的事情,因此我可以直接用对应于输入和输出Web服务消息的C#类映射COBOL结构,如下所示:-
C#:
C#:
namespace MyJSv.Models
{
    public class IJSPG2
    {
        public string JZ_Function { get; set; }
        public int JZ_Employee_Skip { get; set; }
        public class JZEmployee
        {
            public string EMPNO { get; set; }
...
            public string JZ_CURRENCY { get; set; }
        }
        public class ViewState
        {
            public string CheckSum_Employee { get; set; }
        }
    }
}
但是我发现(和 此页面已确认) that I can't refer to IJSPG2.JZEMPLOYEE.EMPNO. To solve the problem I either have to flatten the message layout and deal with name ambiguity by renaming 领域, or use separate classes. I'll handle repeating groups (arrays), by keeping them as separate classes and using C# logic to put the data into an in-memory database (如本教程 )。

在我走这条路之前,可以先有人向我确认,没有办法创建可以用这种方式引用的嵌套类(或结构或任何其他对象类型)。我宁愿不要花费很多精力,然后发现我不需要  :)
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
也许,我没有看到问题。在参加速成班之后 COBOL布局,以下工作对我来说很好:
C#:
namespace ConsoleTest
{
    class MailingRecord
    {
        public class Contact_
        {
            public class President_
            {
                public string LastName { get; set; }
                public string FirstName { get; set; }
            }

            public class VPMarketing_
            {
                public string LastName { get; set; }
                public string FirstName { get; set; }
            }

            public class AlternateContact_
            {
                public string Title { get; set; }
                public string LastName { get; set; }
                public string FirstName { get; set; }
            }

            public President_ President { get; }  = new President_();
            public VPMarketing_ VPMarketing { get; } = new VPMarketing_();
            public AlternateContact_ AlternateContact { get; }  = new AlternateContact_();
        }

        public string CompanyName { get; set; }
        public Contact_ Contact { get; } = new Contact_();
        public string Address { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
    }

    class Program
    {
        static void Main()
        {
            var mailingRecord = new MailingRecord();

            mailingRecord.CompanyName = "Enron";
            mailingRecord.Contact.President.LastName = "Skilling";
            mailingRecord.Contact.President.FirstName = "Jeffrey";
            mailingRecord.Contact.AlternateContact.Title = "CEO";
            mailingRecord.Contact.AlternateContact.LastName = "Lay";
            mailingRecord.Contact.AlternateContact.FirstName = "Kenneth";
        }
    }
}

我怀疑您遇到的绊脚石是C#中不允许以下内容
C#:
class Foo
{
    class Bar
    {
    }

    Bar barInstance;    // !!! Error: CS0102: The type 'Foo' already contains a definition for 'Bar'
}

因此请注意,在我的代码中,我决定使用"_"后缀,然后声明该属性以暴露没有下划线的该类型的实例。
 

罗伯特·NZ

活跃的成员
已加入
2020年6月26日
留言内容
34
编程经验
Beginner
感谢您对跳伞运动员的帮助。我一直在使用VB.NET和ASP.NET>15年了,但是我是C#的新手:我刚刚开始使用它,因为我需要在.NET Core中编写WebAPI,而这需要C#。因此,如果我提出愚蠢的问题,请给一些津贴。另外,我的回答是我在思考正在发生的事情时大声思考。

我已经按照以下样式开发了一个解决方案并开发了MyJSv项目: Web API教程,因此IJSPG2的定义在文件夹Models中。现在,我正在使用program.cs来尝试解决此问题。最初,program.cs是
C#:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
namespace MyJSv
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }
...
    }
}

在我的第一篇文章中定义了IJSPG2之后,我在CreateHostBuilder(args)之前添加(或尝试)了这些语句。
C#:
            var ijspg2 = new Models.IJSPG2();
            ijspg2.JZ_Function = "E";
            ijspg2.JZEmployee.EMPNO = 90;   //  I couldn't write this
唯一的"fields"我可以分配的(= C#类)是JZ_Function和JS_Employee_Skip。要分配给EMPNO,我必须创建另一个定义:-
C#:
            var ijspg2 = new Models.IJSPG2();
            ijspg2.JZ_Function = "E";
            var jzemployee = new Models.IJSPG2.JZEmployee();
            jzemployee.EMPNO = "90";

给类名加后缀的技巧看起来很有趣。我给JZEmployee和Viewstate加了后缀,将定义更改为
C#:
namespace MyJSv.Models
{
    public class IJSPG2
    {
        public string JZ_Function { get; set; }
        public int JZ_Employee_Skip { get; set; }
        public class JZEmployee_
        {
            public string EMPNO { get; set; }
...         public string JZ_CURRENCY { get; set; }
        }
        public class ViewState_
        {
            public string CheckSum_Employee { get; set; }
        }
    }
}
但是仅下划线并没有帮助:如果没有针对jzemployee的单独的类定义,我仍然无法引用ijspg2.JZEmployee.EMPNO。但是然后我意识到您已经向我展示了答案。您不仅在名称后缀,还在MailingRecord类中添加了属性以公开这些较低级的对象。我加了
C#:
public JZEmployee_ JZEmployee { get; set; }
IJSPG2的定义与JZEmployee_类的逻辑级别相同。现在我可以写
C#:
            var ijspg2 = new Models.IJSPG2();
            ijspg2.JZ_Function = "E";
            ijspg2.JZEmployee.EMPNO = "90";
因此,这给了我一个支持COBOL分层记录布局的模型。我认为,使用这些支持属性生成像IJSPG2这样的C#对象要比更改生成方式更简单。 MANASYS爵士乐 生成COBOL。尚需要一段时间才能编译并运行完整的解决方案,但现在很高兴将其设置为“已回答”。谢谢跳伞运动员。
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,500
地点
弗吉尼亚州切萨皮克
编程经验
10+
请注意,我故意执行以下操作:
C#:
public President_ President { get; }  = new President_();
那几乎等于:
C#:
public readonly President_ President = new President_();

The reason why I instantiate the President_ class right away into the President *property* that only has a getter is so that I I won't forget to set it, AND more importantly, after it is set, nobody swaps out the object from under me.

With the the readonly President *field* in the equivalent code, I get the same effect where once the instance is created and set, nobody can swap the object out from under me. But it doesn't follow one of the C# best practices of not exposing public 领域.
 

罗伯特·NZ

活跃的成员
已加入
2020年6月26日
留言内容
34
编程经验
Beginner
谢谢跳伞运动员,我会继续记住这一点。 MANASYS爵士乐 生成带有输入和输出消息IJSPG2和OJSPG2的JSPG2之类的Web服务程序,它们成为CICS Web服务MyJSv中的操作。我的目标是提供一个Web API,其中封装了几乎所有服务规则,如下图所示。然后将简化Web服务的使用,并且类似"必须使用Update将Viewstate保持不变"已实施。客户端验证将立即检测到许多错误,而不是依靠服务器端验证来返回消息,从而提供更好的UI。每个程序都会有自己的API控制器,即"Interface"在图中,其输入和输出消息将是模型中的类层次结构,例如IJSPG2和OJSPG2。在我看来,显而易见的事情是将这些验证规则放入IJSPG2类的Set对象中("fields")。输出(OJSPG2)类可能是只读的。

在开发此功能时,我有很多东西要学习,而且我还会提出很多问题。我非常重视最佳实践方面的指导,因此,感谢您到目前为止的帮助。
.
WebAPI.jpg
 
最佳 底部