Linq select statement prints project.class name as result in output console - c#

I created a class called employees, created three employees. I then created a List<> to store the employee objects
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AutomationTest
{
public class Employees
{
public String ID { get; set; }
public String Name { get; set; }
public List<int> Salary { get; set; }
public static List<Employees> GetEmployeesSalaries()
{
List<Employees> employees = new List<Employees>();
List<int> johnsalary = new List<int> { 1100,1200,1300 };
List<int> jamessalary = new List<int> { 1400, 1450, 1500 };
List<int> timsalary = new List<int> { 1600, 1700, 17500 };
employees.Add(new Employees { ID = "N001", Name = "John", Salary = johnsalary });
employees.Add(new Employees { ID = "N002", Name = "James", Salary = jamessalary });
employees.Add(new Employees { ID = "N003", Name = "Tim", Salary = timsalary });
return employees;
}
}
}
I then created the query statement but got the project.class name on the console output as Automationtest.Employee
using System.Text;
using System.Threading.Tasks;
namespace AutomationTest
{
class Program
{
static void Main(string[] args)
{
IEnumerable<Employees> querysalary = (Employees.GetEmployeesSalaries().Where(i => i.Name.Contains("m"))).ToList<Employees>();
//IEnumerable<Employees> querysalary = from empl in Employees.GetEmployeesSalaries()
// where empl.Name.Contains("a") select empl;
//var querysalary = (from k in Employees.GetEmployeesSalaries() select k).ToString();
foreach (var ss in querysalary)
{
Console.WriteLine(ss);
}
Console.ReadLine();
}
}
}

On Console.WriteLine you are calling the .toString() method of the object wich will give you no readable form of the object. You can override it to create your own implementation. Try to add thid function this in your Employees Class
public override string ToString()
{
return $"{ID} {Name} {String.Join(", ", Salary)}";
}
For the list you have to iterate over the individual entries and put them in a string. This can be done with the String.Join method.
Working example:
public static void Main(string[] args)
{
var character = new Employee();
Console.Write(character);
}
public class Employee
{
public Employee()
{
Salary = new List<int> { 2, 3, 4 };
}
public override string ToString()
{
return $"{String.Join(", ", Salary)}";
}
public List<int> Salary { get; set; }
}

Related

How to call a method multiple times at once for a file

I have a Person model class as following;
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
I get the FirstName and LastName from the user and validate them. Then I create a user name for each first and last name entered by the user with the following method;
public static string CreateUserName(Person person)
{
return $"{person.LastName}{person.FirstName.Substring(0,2)}";
}
I'm able to do this one person at a time by running the program manually each time. What I want to know how to do is, suppose I have multiple lines of data stored in a CSV file which consists of FirstName and LastName and I read that file, then generate a user name for each row in that file at once with my CreateUserName method.
The output will be printed on the console and Person class will be used for other operations also.
Csv content:
FirstName;LastName
FirstName1;LastName1
FirstName2;LastName2
FirstName3;LastName3
Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Logins
{
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Program
{
public static string CreateUserName(Person person) =>
$"{person.LastName}{person.FirstName.Substring(0, 2)}";
static void Main(string[] args)
{
var lines = File.ReadAllLines("test.csv");
var result = lines.Skip(1)
.Aggregate(new Dictionary<string, Person>(), (dict, x) =>
{
var items = x.Split(';');
var person = new Person { FirstName = items[0], LastName = items[1] };
if (!dict.TryAdd(CreateUserName(person), person))
throw new Exception("User with such username already exists!");
return dict;
});
foreach (var item in result)
{
Console.WriteLine($"Username: '{item.Key}' for {item.Value.FirstName} {item.Value.LastName}");
}
}
}
}
Result:
Username: 'LastName1Fi' for FirstName1 LastName1
Username: 'LastName2Fi' for FirstName2 LastName2
Username: 'LastName3Fi' for FirstName3 LastName3
Consider the following demo code:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserName
// Calculate UserName from first and last
=> $"{LastName}{FirstName.Substring(0, 2)}";
public static Person Parse(string csvLine)
// Transform a text line "First, Last" into
// an object of Person
{
var parts = csvLine.Split(',');
if (parts.Length>=2)
{
return new Person()
{
FirstName = parts[0].Trim(),
LastName = parts[1].Trim()
};
}
throw new ArgumentException(nameof(csvLine));
}
}
class Program
{
static void Main(string[] args)
{
var csv = #"First,Last
Jack, Mas
Jake, Moon
John, Mira
Jonas, Master
Jacob, Meek
Josselyn, Moore
Joanna, Milka";
var fs = new System.IO.StringReader(csv);
fs.ReadLine(); // eat up first line
var list = new List<Person>();
while (fs.Peek()!=-1)
{
var person = Person.Parse(fs.ReadLine());
list.Add(person);
}
// create a list of usernames, each in a new line
var unames = string.Join(
Environment.NewLine,
list.Select((person) => person.UserName));
Console.WriteLine(unames);
}
}
That outputs

How to create index based on nested array element in C# Mongodb strongly typed driver

This question is quite on the same principles as this one but I'd like to create an index using strongly typed approach on an object property when this object is nested in an array of the collection.
I can use:
new CreateIndexModel<T>( Builders<T>.IndexKeys.Ascending( a ) )
where a is an Expression which accesses to a direct property.
But I've found nothing similar to:
Builders<Library>.Filter.ElemMatch(x => x.Author.Books, b => b.IsVerified == false));
so that I can define as index some field of an object nested in an array which is a member of the collection.
Is that possible to do it and how?
Consider the following data model:
public class Course
{
public string Name { get; set; }
public string Teacher { get; set; }
}
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public ReadOnlyCollection<Course> Courses { get; set; }
}
You can create an ascending multikey index on the field Courses in the following manner:
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ConsoleApp1
{
public static class Program
{
private static MongoClient Client;
private static IMongoDatabase Database;
private static IMongoCollection<Student> Collection;
public static async Task Main(string[] args)
{
Client = new MongoClient();
Database = Client.GetDatabase("test-index");
Collection = Database.GetCollection<Student>("students");
var courses1 = new List<Course>()
{
new Course { Name = "Math", Teacher = "Bob" }
}.AsReadOnly();
var courses2 = new List<Course>()
{
new Course { Name = "Computer Science", Teacher = "Alice" }
}.AsReadOnly();
var mark = new Student
{
Name = "Mark",
Courses = courses1,
Age = 20
};
var lucas = new Student
{
Name = "Lucas",
Courses = courses2,
Age = 22
};
await Collection.InsertManyAsync(new[] { mark, lucas }).ConfigureAwait(false);
var model = new CreateIndexModel<Student>(
Builders<Student>.IndexKeys.Ascending(s => s.Courses));
await Collection.Indexes.CreateOneAsync(model).ConfigureAwait(false);
Console.WriteLine("All done !");
}
}
}
This query is served by the index you created:
db.students.find({Courses: {"Name": "Math", "Teacher": "Bob"}})
If you don't want to create an index on the entire array Courses, but instead you want an index on the field Name of the nested object (the Course object), this is the way to go:
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ConsoleApp1
{
public static class Program
{
private static MongoClient Client;
private static IMongoDatabase Database;
private static IMongoCollection<Student> Collection;
public static async Task Main(string[] args)
{
Client = new MongoClient();
Database = Client.GetDatabase("test-index");
Collection = Database.GetCollection<Student>("students");
var courses1 = new List<Course>()
{
new Course { Name = "Math", Teacher = "Bob" }
}.AsReadOnly();
var courses2 = new List<Course>()
{
new Course { Name = "Computer Science", Teacher = "Alice" }
}.AsReadOnly();
var mark = new Student
{
Name = "Mark",
Courses = courses1,
Age = 20
};
var lucas = new Student
{
Name = "Lucas",
Courses = courses2,
Age = 22
};
await Collection.InsertManyAsync(new[] { mark, lucas }).ConfigureAwait(false);
var model = new CreateIndexModel<Student>(
Builders<Student>.IndexKeys.Ascending("Courses.Name"));
await Collection.Indexes.CreateOneAsync(model).ConfigureAwait(false);
Console.WriteLine("All done !");
}
}
}
This query is served by the index you created: db.students.explain("executionStats").find({"Courses.Name": "Math"})
A possible way to avoid the usage of magic strings in my second example is exploiting the power of the nameof C# operator:
$"{nameof(Student.Courses)}.{nameof(Course.Name)}"
here's the strongly typed way to created indexes for nested fields using the MongoDB.Entities convenience library. [disclaimer: i'm the author]
using MongoDB.Entities;
using System.Collections.Generic;
namespace StackOverflow
{
public class Program
{
public class Parent : Entity
{
public Child[] Children { get; set; }
}
public class Child
{
public List<Friend> Friends { get; set; }
}
public class Friend
{
public string Name { get; set; }
}
static void Main(string[] args)
{
new DB("test");
DB.Index<Parent>()
.Key(p => p.Children[-1].Friends[-1].Name, KeyType.Ascending)
.Create();
}
}
}
the above creates an ascending index on the name field which is nested two levels deep with the following command:
db.Parent.createIndex({
"Children.Friends.Name": NumberInt("1")
}, {
name: "Children.Friends.Name(Asc)",
background: true
})

Using a Parameter to Call a Class in C#

I have got a method with a single parameter of string class that I need to use to access another class in my project.
The following will be what I want it to do. Note that this syntax gives errors.
public string getId(string name) {
string Id = name.GetId();
return Id;
}
Assuming that the user enters "Joe" as the name, one would go to the class Joe.cs, which looks like this.
public class Joe {
public string Id = 32;
public string GetId() {
return Id;
}
}
What I want to happen here is for the first method to be able to get the GetId method from Joe if Joe is entered as a parameter. How would I do this? Thank you all.
This might point you in a better direction
The idea is to have a class called User that holds user information (funnily enough)
This way you can have a list of users (not a class for each one), as such you can easily look up a user and mess with them as much as you want
public class User
{
public string UserName { get; set; }
public string FavoriteColor { get; set; }
}
public class Program
{
// A List to hold users
private static List<User> _users = new List<User>();
private static void Main(string[] args)
{
// lets add some people
_users.Add(new User() { UserName = "Bob",FavoriteColor = "Red" });
_users.Add(new User() { UserName = "Joe", FavoriteColor = "Green" });
_users.Add(new User() { UserName = "Fred", FavoriteColor = "Blue" });
// use a linq query to find someone
var user = _users.FirstOrDefault(x => x.UserName == "Bob");
// do they exist?
if (user != null)
{
// omg yay, gimme teh color!
Console.WriteLine(user.FavoriteColor);
}
}
}
Output
Red
You can take it a step further and ask the user to look up other users (what a time to be a alive!)
Console.WriteLine("Enter a user (case sensitive)");
var userName = Console.ReadLine();
var user = _users.FirstOrDefault(x => x.UserName == userName);
if (user != null)
{
Console.WriteLine(user.FavoriteColor);
}
else
{
Console.WriteLine("Game over, you failed");
}
Console.ReadLine();
You could build a Class that can contain the details you want to store, then build a Manager class that exposes public methods that can extract informations from the stored objects:
public class Friend : IComparable<Friend>
{
public Friend() { }
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int FriendshipLevel { get; set; }
int IComparable<Friend>.CompareTo(Friend other)
{
if (other.FriendshipLevel > this.FriendshipLevel) return -1;
else return (other.FriendshipLevel == this.FriendshipLevel) ? 0 : 1;
}
}
public class MyFriends : List<Friend>
{
public MyFriends() { }
public int? GetID(string FriendName)
{
return this.Where(f => f.FirstName == FriendName).FirstOrDefault()?.ID;
}
public Friend GetFriendByID(int FriendID)
{
return this.Where(f => f.ID == FriendID).FirstOrDefault();
}
}
Build a sample class:
MyFriends myFriends = new MyFriends()
{
new Friend() { ID = 32, FirstName = "Joe", LastName = "Doe", FriendshipLevel = 100},
new Friend() { ID = 21, FirstName = "Jim", LastName = "Bull", FriendshipLevel = 10},
new Friend() { ID = 10, FirstName = "Jack", LastName = "Smith", FriendshipLevel = 50},
};
Then you can extract informations on single/multiple objects using the public methods of the "Manager" class:
int? ID = myFriends.GetID("Joe");
if (ID.HasValue) // Friend Found
Console.WriteLine(ID);
//Search a friend by ID
Friend aFriend = myFriends.GetFriendByID(32);
if (aFriend != null)
Console.WriteLine($"{aFriend.FirstName} {aFriend.LastName}");
Or you can use LINQ to get/aggregate the required informations directly if there isn't a public method that fits:
// Get your best friends using LINQ directly
List<Friend> goodFriends = myFriends.Where(f => f.FriendshipLevel > 49).ToList();
goodFriends.ForEach((f) => Console.WriteLine($"{f.FirstName} {f.LastName}"));
//Best friend
Friend bestFriend = myFriends.Max();
With respect to your Question : GetId method from Joe if Joe is entered as a
parameter.
You can achieve that in the following ways also:
2. Method Using Named Method.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Problem
{
// Simple Model Class.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
// Delegate.
public delegate string PersonHandler(Person person);
static void Main(string[] args)
{
List<Person> _persons = new List<Person>()
{
new Person(){Id=1,Name="Joe"},
new Person(){Id=2,Name="James"},
new Person(){Id=3,Name="Nick"},
new Person(){Id=4,Name="Mike"},
new Person(){Id=5,Name="John"},
};
PersonHandler _personHandler = new PersonHandler(GetIdOfPerson);
IEnumerable<string> _personIds = _persons.Select(p => _personHandler.Invoke(p));
foreach (var id in _personIds)
{
Console.WriteLine(string.Format("Id's : {0}", id));
}
}
// This is the GetId Method.
static string GetIdOfPerson(Person person)
{
string Id = person.Id.ToString();
return Id;
}
}
}
2. Method Using Anonymous Moethod.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Problem
{
// Simple Model Class.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
// Delegate.
public delegate string PersonHandler(Person person);
static void Main(string[] args)
{
List<Person> _persons = new List<Person>()
{
new Person(){Id=1,Name="Joe"},
new Person(){Id=2,Name="James"},
new Person(){Id=3,Name="Nick"},
new Person(){Id=4,Name="Mike"},
new Person(){Id=5,Name="John"},
};
PersonHandler _personHandler = delegate(Person person)
{
string id = person.Id.ToString();
return id;
};
// Retrieving all person Id's.
IEnumerable<string> _personIds = _persons.Select(p => _personHandler.Invoke(p));
foreach (var id in _personIds)
{
Console.WriteLine(string.Format("Id's : {0}", id));
}
}
}
}
2. Method Using a Lambda Expression.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Problem
{
// Simple Model Class.
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
// Delegate.
public delegate string PersonHandler(Person person);
static void Main(string[] args)
{
List<Person> _persons = new List<Person>()
{
new Person(){Id=1,Name="Joe"},
new Person(){Id=2,Name="James"},
new Person(){Id=3,Name="Nick"},
new Person(){Id=4,Name="Mike"},
new Person(){Id=5,Name="John"},
};
PersonHandler _personHandler = (Person person) => person.Id.ToString();
IEnumerable<string> _personIds = _persons.Select(p => _personHandler.Invoke(p));
foreach (var id in _personIds)
{
Console.WriteLine(string.Format("Id's : {0}", id));
}
}
}
}
Output:

how do i create a Generic List for the class batch and inside class batch i want to put student class information

Here I want to student class inside batch class and use them using the List class, how do I create object of both the classes for List...
Example if I want to find the name of a student from the batch how do I do it...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Challenge
{
class student
{
string student_name;
int age, rollnumber;
public student(string student_name, int age, int rollnumber)
{
this.age = age;
this.student_name = student_name;
this.rollnumber = rollnumber;
}
}
class batch
{
string batch_name;
int fees, duration;
public batch(string batch_name,int fees,int duration)
{
this.batch_name = batch_name;
this.fees = fees;
this.duration = duration;
}
}
class Program
{
static void Main(string[] args)
{
List<batch> obj = new List<batch>();
}
}
}
It is not very clear what you want to do, but I will try to help. From what I can understand, you want to create a collection of Batches, where every Batch contains a collection of Students.
Declare a List<Student> property in the Batch class:
public class Batch
{
public string Name { get; set; }
public int Fee { get; set; }
public int Duration { get; set; }
public List<Student> Students { get; set; }
}
public class Student
{
public string Name { get; set; }
public int RollNumber { get; set; }
// Date of birth instead of age, as explained in comment by Dour High Arch.
public DateTime DateOfBirth { get; set; }
}
You may now create a list of batches by:
var batches = new List<Batch>
{
new Batch
{
Name = "Batch 1",
Duration = 100,
Fee = 200,
Students = new List<Student>
{
new Student
{
Name = "Student 1",
DateOfBirth = DateTime.Today,
RollNumber = 1
},
new Student
{
Name = "Student 2",
DateOfBirth = DateTime.Today,
RollNumber = 2
}
}
}
};
Your batches list can be iterated as:
foreach (var batch in batches)
{
Console.WriteLine($"Batch: {batch.Name}");
foreach (var student in batch.Students)
{
Console.WriteLine($"Student: {student.Name}");
}
}

Get Collections from object using reflection and getCount (.net 4)

I have a requirement to reflect on a object get all properties that are collections and
1)GetCount for each collection
2)GetTotalCount (allCollectionCount)
3)Call a method with this collection.
Below is what I have done so far with a made up noddy structure for semplicity.
I am stuck in how to call this method and how to get count for collection.
Any suggestions?
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main()
{
var request = GetDataRequest();
//Get all properties
List<PropertyInfo> propInfoList =
new List<PropertyInfo>(request.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public));
//Get collections only
var myClassCollections=propInfoList.Where(xxx => xxx.PropertyType.GetInterfaces().Any(x => x == typeof (IEnumerable))).ToList();
var totalCountForAllCollections=????
foreach (var col in myClassCollections)
{
//How do I call my Method DoSomething
// DoSomething<?>(col.?????)
}
}
public void DoSomething<T>(List<T> objectCollection)
{
//etc...
}
private static DataRequest GetDataRequest()
{
DataRequest request = new DataRequest();
request.Addresses.Add(new Address
{
Id = 1,
City = "London",
Postcode = "32131",
Street = "London Road"
});
request.Addresses.Add(new Address
{
Id = 2,
City = "NewYork",
Postcode = "3432",
Street = "NewYork Road"
});
request.Customers.Add(new Customer
{
Id = 1,
Name = "Jo",
Surname = "Bloggs",
});
request.Customers.Add(new Customer
{
Id = 1,
Name = "Jon",
Surname = "Bloggs2",
});
request.Customers.Add(new Customer
{
Id = 1,
Name = "Jonny",
Surname = "Bloggs3",
});
return request;
}
}
public class DataRequest
{
public DataRequest()
{
Customers = new List<Customer>();
Orders = new List<Order>();
Addresses = new List<Address>();
}
public List<Customer> Customers { get; set; }
public List<Order> Orders { get; set; }
public List<Address> Addresses { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
public class Order
{
public int Id { get; set; }
public string Name { get; set; }
public string OrderNo { get; set; }
}
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string Postcode { get; set; }
}
}
quick and dirty, here you go...
// ..
static class Program
{
static void Main()
{
var request = GetDataRequest();
//Get propertyValues for properties that are enumerable (i.e. lists,arrays etc)
var collectionProperties = request.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(propertInfo => propertInfo.PropertyType.GetInterfaces().Any(x => x == typeof(IEnumerable)))
.Select(p => p.GetValue(request, null))
.Cast<IEnumerable<object>>().ToList();
var totalCountForAllCollections = 0;
// iterate through the list of propertyValues
foreach (var collectionPropertyValue in collectionProperties)
{
totalCountForAllCollections += collectionPropertyValue.Count();
collectionPropertyValue.DoSomething();
}
System.Console.WriteLine("The total count for all collections is : {0}", totalCountForAllCollections);
System.Console.WriteLine("press any key to exit");
System.Console.ReadLine();
}
public static void DoSomething<T>(this IEnumerable<T> objectCollection)
{
//etc...
// N.B. you will have to use typeof(T) to implement logic specific to the type
// If the logic in this method is non-specific to the typeof(T) then Implement logic accordingly
System.Console.WriteLine("The type of the collection is: {0}", objectCollection.GetType());
System.Console.WriteLine("The count of items in this collection is:{0}", objectCollection.Count());
}
// ..
}
// ..

Categories