Reputation: 2832
I have no idea what should this question be titled nor keyword to search.
Scenario: I have a model as below
public class Message { public List<Page> Pages { get; set; }
public class Page { public List<Line> Lines { get; set; }
public class Line { public string Text {get; set; }
When I wanted to insert a Line
with Text = "Test"
at Page
1, I would need to do the following.
var Message = new Message();
var line = new Line { Text = "Test" };
var page = new Page();
page.Lines.Add(line);
Message.Pages.Add(page);
Question: are there any easier way to achieve this? Eg.
Message.Pages[0].Lines[0].Text = "Test";
Thanks.
Edit: Assumed all properties are properly instantiated in constructors.
Upvotes: 2
Views: 3757
Reputation: 1631
What Marc and Sergey said. Also you can consider a simplified builder. I replaced the properties with fields to make the example smaller:
public class Message { public List<Page> Pages = new List<Page>(); }
public class Page { public List<Line> Lines = new List<Line>(); }
public class Line { public string Text; }
Then your builder would look something like this:
public class Typewriter
{
Message message = new Message();
Page currentPage;
public Typewriter NewPage()
{
currentPage = new Page();
message.Pages.Add(currentPage);
return this;
}
public Typewriter AddLine(string text)
{
currentPage.Lines.Add(new Line() { Text = text });
return this;
}
}
Then you can do:
var typewriter = new Typewriter();
typewriter.NewPage().AddLine("First line on first page")
.AddLine("Next line on first page")
.NewPage().AddLine("Next page etc");
Upvotes: 0
Reputation: 236308
You can create helper methods in your classes, which will provide handy API for building messages and pages. First is Message class - new Add method accepts page to add, and returns message instance. That will allow to use fluent API for adding pages (example at the bottom):
public class Message
{
public Message()
{
Pages = new List<Page>();
}
public List<Page> Pages { get; private set; }
public Message Add(Page page)
{
Pages.Add(page);
return this;
}
}
And page class. I added static creation method, which builds page with any number of lines you pass to this method:
public class Page
{
public Page()
{
Lines = new List<Line>();
}
public List<Line> Lines { get; private set; }
public static Page WithLines(params string[] texts)
{
var page = new Page();
foreach(var text in texts)
page.Lines.Add(new Line { Text = text });
return page;
}
}
Then adding page with lines will look like
message.Add(Page.WithLines("Text1", "Text2"))
.Add(Page.WithLines("Text3"));
Upvotes: 1
Reputation: 1064184
var msg = new Message {
Pages = new List<Page> {
new Page {
Lines = new List<Line> { new Line { Text = "Test" } }
}
}
};
Note: if the lists are initialized in their respective constructors, you can remove the new List<>
bits:
var msg = new Message {
Pages = {
new Page {
Lines = { new Line { Text = "Test" } }
}
}
};
You could also add an implicit conversion operator from string
to Line
, in which case:
var msg = new Message {
Pages = {
new Page {
Lines = { "Test" }
}
}
};
Edit: fully working example, including operator and ctor initialization, and multiple pages (see comments):
using System.Collections.Generic;
public class Message {
public List<Page> Pages { get; private set; }
public Message() { Pages = new List<Page>(); }
}
public class Page {
public List<Line> Lines { get; private set; }
public Page() { Lines = new List<Line>(); }
}
public class Line {
public string Text { get; private set; }
public static implicit operator Line(string value) {
return new Line { Text = value };
}
}
static class Program {
static void Main() {
var msg = new Message {
Pages = {
new Page {
Lines = { "Test" }
},
new Page {
Lines = {
"On another page",
"With two lines"
},
}
}
};
}
}
Upvotes: 9