C# / Classes and custom types [closed] - c#

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm starting my adventure with C# and don't know all the technics, but I already know what am I trying to achive:
public class Product
{
public string Name { get; set; }
public double Price { get; set; }
//public ??? Category { get; set; }
}
'Category' type should be a custom type (?) which has 8 possible string values for names (Food, clothes etc) and icons specifically for those names (Food - apple.jpg, Clothes - tshirt.jpg and so on)
How do I do that?

Often, when working with fixed size categories (8 in your case) we use enum type:
public enum ProductCategory {
Food,
Clothes,
//TODO: put all the other categories here
}
To add up icons, strings etc. we can implement extension methods:
public static class ProductCategoryExtensions {
// please, notice "this" for the extension method
public static string IconName(this ProductCategory value) {
switch (value) {
case ProductCategory.Food:
return "apple.jpg";
case ProductCategory.Clothes:
return "tshirt.jpg";
//TODO: add all the other categories here
default:
return "Unknown.jpg";
}
}
}
Finally
public class Product {
public string Name { get; set; }
public double Price { get; set; } // decimal is a better choice
public ProductCategory Category { get; set; }
}
Usage
Product test = new Product();
test.Category = ProductCategory.Clothes;
Console.Write(test.Category.IconName());

You can define the Category class like the following with predefined values:
public class Category
{
public static Category Food = new Category("Food", "apple.jpg");
// rest of the predefined values
private Category(string name, string imageName)
{
this.ImageName = imageName;
this.Name = name;
}
public string Name { get; private set; }
public string ImageName { get; private set; }
}
public class Product
{
public string Name { get; set; }
public double Price { get; set; }
public Category Category { get; set; }
}
Then, in your code you can set a product like this:
var product = new Product {Name= "product1", Price=1.2, Category = Category.Food};

So first of all you create a new Class, your custom type
public class Category {
// I recommend to use enums instead of strings to archive this
public string Name { get; set; }
// Path to the icon of the category
public string Icon { get; set; }
}
Now in your product, you can change the line commented out to:
// First Category is the type, the second one the Name
public Category Category { get; set; }
Now you can create a new Product with a category:
var category = new Product() {
Name = "ASP.NET Application",
Price = 500,
Category = new Category() {
Name = "Software",
Icon = "Software.jpg"
}
}
Now when you want to create another Product with another category, just repeat the proccess. You can also create an array of Categories and then use the array elements e.g. Category = Categories[3]. So you create one Category for food, one for Clothes etc, store them all in the array and use them for your products.

Related

Populating DataGridView from JSON Array [duplicate]

This question already has answers here:
How to display JSON data in a DataGridView in WinForms?
(3 answers)
Closed 5 years ago.
I have a JSON with an array of products, which I want to load into my C# program as a list, and eventually, display it in a DataGridView.
JSON:
{
"products":[
{
"name":"game",
"url":"website 1",
"cash_price":"£20.00",
"category":"Playstation 4 Game"
},
{
"name":"tv",
"url":"website 2",
"cash_price":"£200.00",
"category":"electronics"
}
]
}
Product class
class Product
{
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("url")]
public string url { get; set; }
[JsonProperty("cash_price")]
public string cash_price { get; set; }
[JsonProperty("category")]
public string category { get; set; }
[JsonProperty("url")]
public string url { get; set; }
public static IList<Product> products = new List<Product>();
}
I run this code:
string input = File.ReadAllText(openFileDialog1.FileName);
var results = JsonConvert.DeserializeObject(input);
dataGridView1.DataSource = Product.products;
But in the DataGridView, all I'm shown is a blank grid with the headers name, url, cash_price and category. No actual entries inside the grid.
What am I doing wrong?
Thank you
Provide the Product type when deserializing like JsonConvert.DeserializeObject<Product>.
class ProductList
{
public List<Product> products { get; set; }
}
var result = JsonConvert.DeserializeObject<ProductList>(input);
dataGridView1.DataSource = result.products;
You can probably skip the JsonPropertyAttributes when the property name matches the JSON names exactly - as is the case in your example.

C# having Enums of Enums [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Assuming I have an enum category with some values:
enum Category {
ProgrammingBooks
CookingBooks
}
and I want each enum to have his own enum, for instance:
ProgrammingBooks will hold:
enum ProgrammingBooks {
CSharp,
Java,
Cpp
}
I saw a solution suggesting this:
enum Fauna {
enum Type { MAMMAL, BIRD }
TIGER(Type.MAMMAL),
LION(Type.MAMMAL),
PEACOCK(Type.BIRD),
OWL(Type.BIRD);
private final Type type;
Fauna(Type type) { this.type = type; }
}
with the usage:
Stream.of(Fauna.values()).filter(f -> f.type == BIRD).toList()
However, I'm just a beginner and I look for something that even if I do not know and should learn, wont go hardcore on me. I do not understand the example I mentioned (which I found on StackOverFlow).
Use classes or interfaces. For example:
public enum Category
{
ProgrammingBooks,
CookingBooks
}
public interface IBook
{
Category BookType { get; set; }
string Title { get; set; }
string Author { get; set; }
// ...
}
public class ProgrammingBook: IBook
{
public ProgrammingBook()
{
this.BookType = Category.ProgrammingBooks;
}
public string Author { get; set; }
public string Title { get; set; }
public Category BookType { get; set; }
// ...
}
public class CookBook : IBook
{
public CookBook()
{
this.BookType = Category.CookingBooks;
}
public string Author { get; set; }
public string Title { get; set; }
public Category BookType { get; set; }
// ...
}
If you want to support "sub-types" you could provide properties that only belong to a specific class and not into the interface because not every book is about programming. For example:
public enum ProgrammingLanguage
{
CSharp,
Java,
Cpp
}
public class ProgrammingBook: IBook
{
// a constructor that takes the ProgrammingLanguage as argument
public ProgrammingBook(ProgrammingLanguage language)
{
this.BookType = Category.ProgrammingBooks;
this.Language = language;
}
public ProgrammingLanguage Language { get; set; }
public string Author { get; set; }
public string Title { get; set; }
public Category BookType { get; set; }
// ...
}
Why i use interfaces at all? Because all books have something in common(f.e. they all have a title and an author). So you can benefit from Polymorphism:
var library = new List<IBook>();
var book1 = new ProgrammingBook(ProgrammingLanguage.CSharp) {Title = "C# in Depth", Author = "Jon Skeet"};
var book2 = new CookBook() { Title = "Everyday Superfood", Author= "Jamie Oliver" };
library.Add(book1);
library.Add(book2);
// now you can loop all and you know that all books have these properties
foreach (IBook book in library)
{
Console.WriteLine("Title: {0} Type: {1}", book.Title, book.BookType.ToString());
}
or if you only want to get programming-books:
foreach (IBook book in library.Where(b => b.BookType == Category.ProgrammingBooks))
{
// ...
}
the same with LINQ's Enumerable.OfType method which just checks the type:
foreach (IBook book in library.OfType<ProgrammingBook>())
{
// ....
}
Enum is just a representation of an integer with text. It cannot hold sub categories or anything but an integer.
You should create a class for the categories and hold an enum of the sub categories in each of them.
public class ProgrammingBook
{
public BookType Type{get;set;}
}
enum BookType {
CSharp,
Java,
Cpp
}

How flatten a list with many arrays inside using LINQ

I am finding this very hard to understand and where to start, so I was hoping that some one would be able to point in the correct direction. I have a list(customers) inside which there are arrays/lists. Basically I want to flatten all the results of the list into a flat version if the list.
public class Customer : EntityBase
{
public Phonenumber[] PhoneNumbers { get; set; }
public Contact BillToContact { get; set; }
public Terms Terms { get; set; }
}
public class Contact
{
public Phonenumber[] PhoneNumbers { get; set; }
public Address Address { get; set; }
public Key Key { get; set; }
public string CompanyName { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
}
public class Phonenumber
{
public string Number { get; set; }
public int Key { get; set; }
}
public class Terms
{
public int DueDays { get; set; }
public int DiscountDays { get; set; }
}
public class Address
{
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string Country { get; set; }
}
public abstract class EntityBase
{
public Guid Id { get; set; }
public string Status { get; set; }
public int Rev { get; set; }
}
I have tried many approaches and just keep getting more confused. So if anyone could help or even point me in the right direction I would be extremely grateful. below is one of the approaches I have tried.
public IEnumerable<Customer> Find (Func<Customer , bool> predicate) {
foreach (var p in Customer.SelectMany(p => p)) {
if(predicate(p)) {
yield return p;
}
}
}
I am Deserializing a jason string into a list but then want to display in a datagrid, but igGrid does not support binding to nested(complex) properties. So I need to flatten the list so that there is no sub levels of the list.
To select an array of PhoneNumber from List<Customer> use SelectMany:
List<Customer> customers = [data];
PhoneNumber phoneNumbers = customers.SelectMany(x=>x.PhoneNumbers).ToArray();
It's not clear at all from your question what output you actually want. Do you just want a list of all the phone numbers? Or do you want to preserve the other Customer information, such that you get multiple instances of the Customer information, each instance with a separate phone number?
You can accomplish the former with something like this:
IEnumerable<Phonenumber> numbers =
customers.SelectMany(
customer => customer.PhoneNumbers
.Concat(BillToContact.PhoneNumbers));
If you only want the Customer.PhoneNumbers numbers and not those in the BillToContact object, just leave the .Concat(BillToContact.PhoneNumbers) out of the above.
If you want to preserve one or more values from the original Customer object, you can do something like this:
var numbers = customers.SelectMany(
customer => customer.PhoneNumbers.Select(
number => new
{
Number = number,
FirstName = customer.BillToContact.FirstName,
Email = customer.BillToContact.Email
}));
The above will generate an enumeration of anonymous type objects, each having a single phone number, along with the corresponding FirstName and Email values from the associated Contact object. You can of course mix and match (e.g. use .Concat(...) to include phone numbers from the BillToContact object), and include whichever specific Customer or Contact members you want.

How do I update a record that has a child entity?

I am trying to update a record and its child at the same time. When I create the object from the database the child property is null (the property is a generic list).
I want to update the class and also update the child class without creating duplicated records in the system.
Here is how I generate the object:
var r = db.SupplierAs.Where(o => o.id == 1).First();
The SupplierA class has a property List. Using the above line of code this comes back null. I have been trying work out the code to initialize this property so I can update it but I am having no joy.
This is the original item I created:
db.Products.Add(new Product
{
name = "product test",
supplierA = new SupplierA
{
name = "supA",
price = 1.99m,
sku = "abc123",
otherCurrencies = new List<Currency>
{
new Currency
{
eur = 2.99m,
usd = 3.99m
}
}
},
});
db.SaveChanges();
I can update the supplier on its own easily like so:
var r = db.SupplierAs.Where(o => o.id == 1).First();
r.name = "Updated name";
db.SupplierAs.Attach(r);
db.Entry(r).State = EntityState.Modified;
db.SaveChanges();
But I cannot figure out how to generate the Currency object list as part of the SupplierAs object. Currencies doesnt seem to be in the db context.
Here are the class files:
public class Product
{
public int id { get; set; }
public string name { get; set; }
public virtual SupplierA supplierA { get; set; }
}
public class SupplierA
{
public int id { get; set; }
public string name { get; set; }
public string sku { get; set; }
public decimal price { get; set; }
public List<Currency> Currencies { get; set; }
}
public class Currency
{
public int id { get; set; }
public decimal eur { get; set; }
public decimal usd { get; set; }
}
The idea of products, suppliers and currencies doesn't make the greatest sense I know, I have extracted logic from my app in example, hopefully it makes enough sense what I am trying to achieve.

How to define default values with Entity Framework C#?

Models in question:
public class EmployeeType
{
public int employeeTypeId { get; set; }
public string typeName { get; set; }
public virtual List<Employee> Employees { get; set; }
}
public class Employee
{
public int employeeId { get; set; }
public string userName { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string password { get; set; }
public int employeeTypeId { get; set; }
public virtual EmployeeType EmployeeTypes { get; set; }
public virtual List<PhoneNumber> PhoneNumbers { get; set; }
}
At the moment i am adding different values through:
db.EmployeeType.Add(new EmployeeType
{
typeName = "Administrator"
});
db.EmployeeType.Add(new EmployeeType
{
typeName = "Seller"
});
db.EmployeeType.Add(new EmployeeType
{
typeName = "Accountant"
});
But in a case when i have to check if the user is an administrator or etc. i have to check through linq query and find out if the id is equal to the id in the Employee table.
How could i define default records in the EmployeeType model and not add the values through multiple .Add lines, so that i could use something like this:
if (db.Employee.FirstOrDefault(o => ...).servictypeId
== EmployeeType.Administrator)
{
}
The best way to handle this would be to convert employeetypeId into an enum in EF. You can easily achieve this by "converting" the field into an enum within the EDMX. Just right click on the property in the edmx model design screen and click "convert to enum".
Firstly though, you need to create an Enum, Called UserRole :-
enum UserRole : int
{
Administrator = 1,
Manager = 2,
Client = 3
}
Now, when you want to make new UserRole's you add them in your Enum.
When it comes to adding a new user, you simply do the following :-
new User object1 { Name = "Fred", UserRole = UserRole.Client};
dbContext.Save(object1);
EF will know to save the employeeTypeId as 3 in the database.
The advantage gets better, because now you can say :-
if(User.UserRole == UserRole.Adminstartor)
{
//Do Stuff
}

Categories