Creating a List<Book> c# console application - c#

I want to create a List that holds a couple of books with the book title, authors name and year of publication. example: ( AuthorLastName, AuthorFirstName, “The book title”, year.)
I know how to create List<int>, for example:
class Program
{
static void Main()
{
List<int> list = new List<int>();
list.Add(10);
list.Add(20);
list.Add(25);
list.Add(99);
}
}
But the problem is, if I want to create a list of books, I can't simply make a list<string> or list<int> because I want it to contain strings and int's (as the example above).
So, Can anyone explain how I can make a List of books?

You need to create a class called Book that contains the properties you want to have. Then you can instantiate a List<Book>.
Example:
public class Book
{
public string AuthorFirstName { get; set; }
public string AuthorLastName { get; set; }
public string Title { get; set; }
public int Year { get; set; }
}
And then, to use it:
var myBookList = new List<Book>();
myBookList.Add(new Book {
AuthorFirstName = "Some",
AuthorLastName = "Guy",
Title = "Read My Book",
Year = 2013
});

You need to define your class:
public class Book
{
public string Author { get; set; }
public string Title { get; set; }
public int Year { get; set; }
}
Then you can make a list of them:
var listOfBooks = new List<Book>();

Do something like this
public class Book
{
public string AuthorLastName { get; set; }
public string AuthorFirstName{ get; set; }
public string Title{ get; set; }
public int Year { get; set; }
}
List<Book> lstBooks = new List<Book>();
lstBooks.Add(new Book()
{
AuthorLastName = "What",
AuthorFirstName = "Ever",
Title = Whatever
Year = 2012;
});

Related

C# Class Initialize and set data and List information

I am able to set the values for each item in ROOT, such as Address_to and Line_items, but when I try to pass the populated class to Post, it's empty.
public class OrdersClass
{
public class Line_items
{
public string sku { get; set; }
public int quantity { get; set; }
}
public class Address_to
{
public string first_name { get; set; }
public string last_name { get; set; }
public string address1 { get; set; }
public string address2 { get; set; }
public string city { get; set; }
public string zip { get; set; }
}
public class Root
{
public string external_id { get; set; }
public IList<Line_items> line_items { get; set; }
public Address_to address_to { get; set; }
}
}
My c# code:
OrdersClass.Root thisOrder = new OrdersClass.Root();
thisOrder.address_to = new OrdersClass.Address_to();
IList<OrdersClass.Line_items> lineItems = new List<OrdersClass.Line_items>();
I can populate address_to as
thisOrder.address_to.first_name "my first name";
and line_items using:
lineItems.Add(new OrdersClass.Line_items());
lineItems[0].sku = ProductSKU;
lineItems[0].quantity = cartQuantity;
but..I know I'm doing this wrong.
Thanks.
You need to add Line_items:
IList<OrdersClass.Line_items> lineItems = new List<OrdersClass.Line_items>();
var lineItem1 = new OrdersClass.Line_items()
{
quantity = 1,
sku = "sku1"
};
lineItems.Add(lineItem1);
var lineItem2 = new OrdersClass.Line_items()
{
quantity = 2,
sku = "sku2"
};
lineItems.Add(lineItem2);
try to use
lineitems.Add(new OrderClass.Line_items(){
sku = ProductSKU,
quantity = cartQuantity
});
Thanks to those who helped me get my thinking cap back on. Resolved.
line_items.Add did not add the iList to the main "thisOrder" class.
I had instantianted it syntactically correct, but it programmatically correct.
This worked:
thisOrder.line_items = new List<OrdersClass.Line_items>();
Then adding a new ilist:
var lineItem = new OrdersClass.Line_items()
{
quantity = cartQuantity,
sku = printifyProductSKU
};
thisOrder.line_items.Add(lineItem);
Yea. Now on the to the programming challenge:ASYNC Post vs Put.
Thanks.

C# how to loop json2csharp generated classes lists

After using http://json2csharp.com/ I got this stucture and I am trying to loop through all Books, however I don't know how and I guess there is a better way then to getting every Book list by hand like this BookStores[0].Prism.Books
In short I want to loop through every List<Book>
public class Book
{
public string name { get; set; }
public int pages { get; set; }
public double rating { get; set; }
public bool available { get; set; }
}
public class Prism
{
public List<Book> Books { get; set; }
}
public class Paragraphia
{
public List<Book> Books { get; set; }
}
public class BookStore
{
public Prism Prism { get; set; }
public Paragraphia Paragraphia { get; set; }
}
public class RootObject
{
public List<BookStore> BookStores { get; set; }
}
What about the following implementation.
public class Book
{
public string name { get; set; }
public int pages { get; set; }
public double rating { get; set; }
public bool available { get; set; }
}
public enum BookCategory
{
Prism,
Paragraphia
}
public class BookStore
{
public Dictionary<BookCategory, List<Book>> Books { get; set; }
}
And then use it as follows:
var bookStore = new BookStore();
bookStore.Books = new Dictionary<BookCategory, List<Book>>();
var paragrapiaBooks = new List<Book>();
paragrapiaBooks.Add(new Book{name = "Paragrapia book 1"});
paragrapiaBooks.Add(new Book{name = "Paragrapia book 2"});
bookStore.Books[BookCategory.Paragraphia] = paragrapiaBooks;
var prismBooks = new List<Book>();
prismBooks.Add(new Book{name = "Prism book 1"});
prismBooks.Add(new Book{name = "Prism book 2"});
bookStore.Books[BookCategory.Prism] = prismBooks;
foreach (var bookCategory in bookStore.Books)
{
foreach (var book in bookCategory.Value)
{
Console.WriteLine(book.name);
}
}
Console.ReadLine();
This way your implementation is also more flexible, you don't have to add a new property when you need a new book category, you just have to add a new Enum value. Instead of an Enum you can also use a String for example.
======================================================================
But I think the following solution is better, by adding property category to the Book class, because it is in fact a property of the book and not of the collection of books. A science fiction novel will still be science fiction even when it is placed on a bookshelf full of cookbooks.
public class Book
{
public string name { get; set; }
public int pages { get; set; }
public string category { get; set; }
public double rating { get; set; }
public bool available { get; set; }
}
public class BookStore
{
public List<Book> Books { get; set; }
}
And then use it as follows:
var bookStore = new BookStore();
bookStore.Books = new List<Book>();
bookStore.Books.Add(new Book { name = "Paragrapia book 1", category = "Paragrapia" });
bookStore.Books.Add(new Book { name = "Paragrapia book 2", category = "Paragrapia" });
bookStore.Books.Add(new Book { name = "Prism book 1", category = "Prism" });
bookStore.Books.Add(new Book { name = "Prism book 2", category = "Prism" });
Console.WriteLine("ONLY PRISM BOOKS:");
foreach (var book in bookStore.Books.Where(b => b.category == "Prism"))
{
Console.WriteLine(book.name);
}
Console.WriteLine("\r\nALL BOOKS:");
foreach (var book in bookStore.Books)
{
Console.WriteLine(book.name);
}
Console.ReadLine();

A Class with List(T) property inside a Class with a List(T) property

I'm starting to program in C# .NET. I've made a web calendar for workers where they can view how many days they didn't go to work due a disease, holidays, etc.
At first I did it with 2 arrays. One for a full calendar with these dimensions:
calendar[person_code][month][day][6 items] -> calendar[int][int][int][object (starting absence date, type of absence, etc)]
The other one is an array with one worker definition like
person[person_code][13 items] -> person[int][13 string (name, surname, etc)]
I'd like to do this with classes to improve my code. I've thinking about the classes above:
public class absence
{
public int absenceCode { get; set; }
public int typeAbsence { get; set; }
public DateTime startingDate { get; set; }
public DateTime endingDate { get; set; }
public string description { get; set; }
public string state { get; set; }
public constructors...
}
public class calendar
{
public int day { get; set; }
public int month { get; set; }
public absence absen { get; set; }
public contructors....
}
public class person
{
public int personCode { get; set; }
public string surname { get; set; }
public string name { get; set; }
public string address { get; set; }
public int maxHolidayDays { get; set; }
public calendar calend { get; set; }
public constructors....
}
That is my code but I don't know how to handle to set and retrieve information like working with arrays.
I can create a new instance of person for each one but I'd need to create some absences in a unique day. (One worker could absent from work some times in a day)
I had though about using a List(T) class like
List<person> = new List<person>(), and List<absence> = new List<absence>()
but how could I set a List<absence>() nested in a one day of "calendar" class?
I need to set that List inside a calendar day wich belows a person from a List :/
List<person> -> calendar -> List<absence>
I hope it's enough clear for you.
Regards.
I would do it like this.
1.Skip calendar class
2.In person class add collection of absences (e.g. List)
3.If you have IEnumerable (e.g. List, person[]) you can search for data you need
public class absence
{
public int absenceCode { get; set; }
public int typeAbsence { get; set; }
public DateTime startingDate { get; set; }
public DateTime endingDate { get; set; }
public string description { get; set; }
public string state { get; set; }
}
public class person
{
public int personCode { get; set; }
public string surname { get; set; }
public string name { get; set; }
public string address { get; set; }
public int maxHolidayDays { get; set; }
// Initialize in constructor if you have an error
public List<absence> absences { get; set; } = new List<absence>();
}
As for searching it would be quite easy. Lets say you need people absent at specific date:
IEnumerable<person> Persons = GetPersonsList();
DateTime dateToCheck = GetAbsentDate();
var absentPersons = Persons.Where(x=>x.absences.Any(a=>a.startingDate>= dateToCheck&&a.endingDate<= dateToCheck));
First of all, as user3185569 mentioned in the comment to the question, you have change your code using this instruction: Capitalization Conventions
Secondly, you have to think about data representation. What kind if relationship becomes between person and absence? One person may have several absences (a 1:N relationship). So, you have to store data about absences and a person related with this absence.
Classes:
public class Person
{
public int PersonCode { get; set; }
public string Surname { get; set; }
public string Name { get; set; }
public string Address { get; set; }
//constructor, etc.
public override string ToString()
{
return string.Format("{0} {1} {2} {3}", PersonCode, Surname, Name, Address);
}
}
public class Absence
{
public int AbsenceCode { get; set; }
public int TypeAbsence { get; set; }
public DateTime StartingDate { get; set; }
public DateTime EndingDate { get; set; }
public string Description { get; set; }
public string State { get; set; }
//"a link" to person
public Person Person { get; set; }
//constructor, etc.
public override string ToString()
{
return string.Format("{0}\t|\t{1}\t{2}\t{3}", Person.ToString(), TypeAbsence.ToString(),
StartingDate.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture),
EndingDate.ToString("yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture));
}
}
Usage:
List<Person> persons = new List<Person>()
{
new Person() {PersonCode = 1, Surname = "Los", Name = "Maciej", Address = "Poland, ..."},
new Person() {PersonCode = 2, Surname = "Doe", Name = "John", Address = "USA, ..."},
new Person() {PersonCode = 3, Surname = "McAlister", Name = "Fred", Address = "UK, ..."},
new Person() {PersonCode = 4, Surname = "Sommer", Name = "Anna", Address = "Canada, ..."},
};
List<Absence> absences = new List<Absence>()
{
new Absence(){AbsenceCode = 1, TypeAbsence=1, StartingDate = new DateTime(2017,5,11), EndingDate = new DateTime(2017,5,15),
Description = "whatever", State = "A", Person = persons[0]},
new Absence(){AbsenceCode = 2, TypeAbsence=1, StartingDate = new DateTime(2017,5,18), EndingDate = new DateTime(2017,6,8),
Description = "whatever", State = "A", Person = persons[1]},
new Absence(){AbsenceCode = 3, TypeAbsence=2, StartingDate = new DateTime(2017,6,1), EndingDate = new DateTime(2017,6,12),
Description = "whatever", State = "B", Person = persons[2]},
new Absence(){AbsenceCode = 4, TypeAbsence=2, StartingDate = new DateTime(2017,6,1), EndingDate = new DateTime(2017,6,5),
Description = "whatever", State = "B", Person = persons[0]},
new Absence(){AbsenceCode = 5, TypeAbsence=1, StartingDate = new DateTime(2017,6,2), EndingDate = new DateTime(2017,6,5),
Description = "whatever", State = "A", Person = persons[2]}
};
//define date-range to filter Absences data
DateTime dfrom = new DateTime(2017,6,5);
DateTime dTo = new DateTime(2017,6,9);
var LastWeekAbsencesByPerson = absences
.Where(x=> (x.StartingDate<=dTo) && (x.EndingDate>=dfrom))
.OrderBy(x => x.Person.Surname)
.ThenBy(x => x.StartingDate)
.ToList();
foreach(var lwabp in LastWeekAbsencesByPerson)
{
Console.WriteLine("{0}", lwabp.ToString());
Console.WriteLine("{0}", new string('-', 60));
}
On the same manner, you can filter data by date, person, type of absence, etc.
As to the date filter, i'd strongly recommend to read this: Determine Whether Two Date Ranges Overlap
There's a lot of things to do, to improve, but this is your job.
Good luck!

Two generics and infinity

I have two interfaces. I want to use them for list and for array.
public interface IBook<T>
{
string Name { get; set; }
T Authors { get; set; }
int PagesCount { get; set; }
}
public interface IAuthor<T>
{
string Name { get; set; }
T Books { get; set; }
}
class Author<T> : IAuthor<IBook<T>[]>
where T : IAuthor<IBook<T>[]>
{
public string Name { get; set; }
public IBook<T>[] Books { get; set; }
}
class Book<T> : IBook<IAuthor<T>[]>
where T : IBook<IAuthor<T>[]>
{
public string Name { get; set; }
public IAuthor<T>[] Authors { get; set; }
public int PagesCount { get; set; }
public static void Main(string[] args)
{
Author<IBook<IAuthor<...>[]>[]> a = new Author<>();
}
}
Is there any way to create object like this in main. The compiler says there are no errors in description of interfaces and classes. Please help me.
Personally, I think that you may be over-using generics here and making this a little bit more complex than it is.Evaluate your criteria:
Author (one -> many) Book
Book (one -> many) Author
You can do this by having the following classes:
public class Book
{
public string Name { get; set; }
public Author[] Authors { get; set; }
public int PageCount { get; set; }
}
public class Author
{
public string Name { get; set; }
public Book[] Books { get; set; }
}
If you make it like this, you can make your life somewhat easier by containing all books and authors within a parent class and using linq queries to identify which object a book / author is related to:
public class BookStore
{
public List<Book> Books { get; set; }
public List<Author> Authors { get; set; }
public Book GetBook(string name)
{
var query = Books.Where(b => b.Name.Equals(name));
if (query.Count() == 1)
return query.ElementAt(0);
else return null;
}
public Author GetAuthor(string name)
{
var query = Authors.Where(a => a.Name.Equals(name));
if (query.Count() == 1)
return query.ElementAt(0);
else return null;
}
}
It would definitely be better for you if you don't use generic classes like this, cause this will be a pain in the neck every time you try to initialise an object. At least you make a default implementation for the generic class where it doesn't need to be given a type of author. You should definitely implement some kind of strategy for your application which will depend on how scalable it should be and easy to maintain and #Nathangrad has given you a great example.
I think your objects should look something like this where your Book's authors are not open to be changed directly and Author's books as well:
public interface IBook
{
string Name { get; set; }
ICollection<IAuthor> GetAuthors();
void AddAuthor(IAuthor book);
int PagesCount { get; set; }
}
public interface IAuthor
{
string Name { get; set; }
ICollection<IBook> GetBooks();
void AddBook(IBook book);
}
public class Author : IAuthor
{
private ICollection<IBook> books;
public Author()
{
this.books = new HashSet<IBook>();
}
public Author(ICollection<IBook> books)
{
this.books = books;
}
public string Name { get; set; }
public void AddBook(IBook book)
{
this.books.Add(book);
}
public ICollection<IBook> GetBooks()
{
return this.books;
}
}
public class Book : IBook
{
private ICollection<IAuthor> authors;
public Book()
{
this.authors = new HashSet<IAuthor>();
}
public Book(ICollection<IAuthor> Authors)
{
this.authors = Authors;
}
public void AddAuthor(IAuthor author)
{
this.authors.Add(author);
}
public ICollection<IAuthor> GetAuthors()
{
return this.authors;
}
public string Name { get; set; }
public int PagesCount { get; set; }
}

How do I serialize a class with properties declared as interfaces?

Here is my list of classes:-
public interface IUniquelyIdentifiable
{
string AuthorName { get; set; }
}
public interface IUniquelyIdentifiable1
{
string CategoryName { get; set; }
}
public interface IUniquelyIdentifiable2
{
string PublisherName { get; set; }
}
[Serializable]
public class Book
{
//BookId, Category, Title, Author, Publisher, Description, Price, ISBN, PublicationDate.
public IUniquelyIdentifiable Author { get; set; }
public IUniquelyIdentifiable1 Category { get; set; }
public IUniquelyIdentifiable2 Publisher { get; set; }
public int BookId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int ISBN { get; set; }
public int Price { get; set; }
public string PublicationDate { get; set; }
}
[Serializable]
class Author : IUniquelyIdentifiable
{
//AuthorId, AuthorName, DateOfBirth, State, City, Phone
public int AuthorId { get; set; }
public string AuthorName { get; set; }
public string DateOfBirth { get; set; }
public string State { get; set; }
public string City { get; set; }
public int Phone { get; set; }
}
[Serializable]
class Category : IUniquelyIdentifiable1
{
//CategoryId, CategoryName, Description
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string Description { get; set; }
}
[Serializable]
class Publisher : IUniquelyIdentifiable2
{
//PublisherId, PublisherName, DateOfBirth, State, City, Phone.
public int PublisherId { get; set; }
public string PublisherName { get; set; }
public string DateOfBirth { get; set; }
public string State { get; set; }
public string City { get; set; }
public int Phone { get; set; }
}
below is the method which is trying to serialize the objects created of the above classes:-
public static void XmlSerializeMyObject()
{
XmlSerializer writer = new XmlSerializer(typeof(Book));
//overview.title = "Serialization Overview";
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "//SerializationOverview.xml";
FileStream file = File.Create(path);
writer.Serialize(file,bookList);
file.Close();
}
As you can see I even used the attribute [Serializable] but still getting the error that I cant serialize interfaces.
Also I just want serialize the objects of the given classes and not interfaces.
See the comments at the end. My first solution answers the question directly but I don't recommend doing it unless you have no choice. Short version - I recommend solving the problem by using the concrete types Author, Category, and Publisher instead of interfaces in the Book class.
In order to serialize a type there must be some way of determining what the concrete types of the members are. It's possible that something could serialize an instance of Book using an implementation of IUniquelyIdentifiable that is unknown to the application deserializing it.
You can modify your Book class like this:
[Serializable][DataContract][KnownType(typeof(Author))]
[KnownType(typeof(Category))]
[KnownType(typeof(Publisher))]
public class Book
{
[DataMember]public IUniquelyIdentifiable Author { get; set; }
[DataMember]public IUniquelyIdentifiable1 Category { get; set; }
[DataMember]public IUniquelyIdentifiable2 Publisher { get; set; }
[DataMember]public int BookId { get; set; }
[DataMember]public string Title { get; set; }
[DataMember]public string Description { get; set; }
[DataMember]public int ISBN { get; set; }
[DataMember]public int Price { get; set; }
[DataMember]public string PublicationDate { get; set; }
}
Then use a DataContractSerializer to serialize. Here's an example:
using (var sw = new StringWriter())
{
using (var xw = new XmlTextWriter(sw))
{
var book = new Book();
book.Author = new Author { AuthorName = "Bob" };
book.Category = new Category { CategoryId = 5 };
book.Publisher = new Publisher { City = "Clearwater" };
var serializer = new DataContractSerializer(typeof(Book));
serializer.WriteObject(xw, book);
var output = sw.ToString();
Assert.IsNotNull(sw);
}
}
This answers the question, but it doesn't solve any problems. In fact, it creates a new problem.
If you just declare the Author, Category, and Publisher properties of Book as concrete types, then you're constrained to using those types. The compiler will show an error if you try to set that property using any class that isn't Author.
But if you add the KnownType attribute as above, the problem is even worse because it's hidden. Now you can set Author to anything implementing IUniquelyIdentifiable. But when you do that (perhaps in some other part of your application) you have no way of knowing that it will fail when serialized. The constraint is still there - you still have to use Author. The difference is that now you get a runtime exception instead of a compile error.
You could instead specify a list of known types to the DataContractSerializer. That gives you a way to specify more types, even using reflection to get a list of types that implement the interface.
But it's still problematic. It's a hidden constraint. You're saying that the type of the property is IUniquelyIdentifiable. According to proper OOP design and the Liskov substitution principle you should be able to use any implementation of that interface. But in reality you can't use any implementation. You have to use one that may or may not be labeled as a "known" type somewhere else (or in multiple places) in your code. Someone could break your application at any time without causing a compile error.
Based on that I'd say to only use the above methods if you have no choice, like if you have to serialize something that you didn't design. If you're writing your own classes then I would just declare Book using the concrete types Author, Category, and Publisher.
You can't serialize interfaces. It doesn't work.
your solution is to change Book's properties to the actual serializable classes:
[Serializable]
public class Book
{
//BookId, Category, Title, Author, Publisher, Description, Price, ISBN, PublicationDate.
public Author Author { get; set; }
public Category Category { get; set; }
public Publisher Publisher { get; set; }
public int BookId { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int ISBN { get; set; }
public int Price { get; set; }
public string PublicationDate { get; set; }
}
The question #Richard_Everett linked contain the same answer. Sorry I can't provide any better solution.

Categories

Resources