How do I go about removing the optional field from the text field that I have output using the Filehelpers library. I'm using c#
For example,
I have a shared class file
with attributes such as recordnumber, filler, payment, endingspaces
Then I need to write only recordnumber and payment into the text file without the filler.
[FixedLengthRecord(FixedMode.ExactLength)]
public partial class Person
{
[FieldFixedLength(10)]
public string FirstName;
[FieldFixedLength(10)]
public string LastName;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional1;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional2;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional3;
}
class Program
{
private static void Main(string[] args)
{
var engine = new FileHelperEngine<Person>();
Person[] allPersonRecords = GetPersonExportFromDataBase() as Person[];//This will only get the FirstName,LastName,Optional2. No result for Optional1 and Optional3
FileHelperEngine enginePerson = new FileHelperEngine(typeof(Person));
enginePerson.AppendToFile(FileName, allPersonRecords ); //Write the records to the file
//Current Output looks like this:John Lee title
//The output which I want is:John Lee title
}
}
You can use the INotifyWrite attribute to intercept the line before it is written and modify it. Here is a working example.
[DelimitedRecord(",")]
public partial class Person : INotifyWrite<Person>
{
public string FirstName;
public string LastName;
[FieldOptional]
public string Optional1;
[FieldOptional]
public string Optional2;
[FieldOptional]
public string Optional3;
public void BeforeWrite(BeforeWriteEventArgs<Person> e)
{
}
public void AfterWrite(AfterWriteEventArgs<Person> e)
{
// count the non-optional fields
var numberOfNonOptionalFields = typeof(Person).GetFields()
.Where(f => !f.GetCustomAttributes(false).Any(a => a is FieldOptionalAttribute))
.Count();
// take only the first n tokens
e.RecordLine = String.Join(",", e.RecordLine.Split(',').Take(numberOfNonOptionalFields));
}
}
class Program
{
private static void Main(string[] args)
{
var engine = new FileHelperEngine<Person>();
var export = engine.WriteString(
new Person[] {
new Person() {
FirstName = "Joe",
LastName = "Bloggs",
Optional1 = "Option 1",
Optional2 = "Option 2",
Optional3 = "Option 3"
}
});
Assert.AreEqual("Joe,Bloggs" + Environment.NewLine, export);
Console.WriteLine("Export was as expected");
Console.ReadLine();
}
}
If you want to just statically omit the optional fields (i.e. they are never used and you never want to output them) you could just create another class representing the desired output format and then convert the list from one object type to another using LINQ:
class Program
{
static void Main(string[] args)
{
// dummy test data
var originalAllPersonRecords = new Person[]
{
new Person { FirstName = "John", LastName = "Lee", Optional2 = "title" },
};//This will only get the FirstName,LastName,Optional2. No result for Optional1 and Optional3
var allPersonRecords = from p in originalAllPersonRecords select new OutputPerson{ FirstName = p.FirstName, LastName = p.LastName, Optional2 = p.Optional2 };
FileHelperEngine enginePerson = new FileHelperEngine(typeof(OutputPerson));
string fileName = "Wherever you want the file to go";
enginePerson.AppendToFile(fileName, allPersonRecords); //Write the records to the file
//Current Output looks like this:John Lee title
//The output which I want is:John Lee title
}
}
//New class added representing the output format
[FixedLengthRecord(FixedMode.ExactLength)]
class OutputPerson
{
[FieldFixedLength(10)]
public string FirstName;
[FieldFixedLength(10)]
public string LastName;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional2;
}
[FixedLengthRecord(FixedMode.ExactLength)]
class Person
{
[FieldFixedLength(10)]
public string FirstName;
[FieldFixedLength(10)]
public string LastName;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional1;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional2;
[FieldOptional]
[FieldFixedLength(5)]
public string Optional3;
}
Related
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
so I have a list of objects in my program that objects in it have (name, last name, id, house, etc.)
I want to create a method called search that lets me find a specific object only with its name. I want to print out the information after search.
(i have one parent class caled wizard and two child classes. one for teachers and one for students(WizardToBe).)
List<WizardTobe> WizardStudents = new List<WizardTobe>();
I received all the information needed below using Readline so all of these are user input.
and all of my codes are in a while loop.
string studentname = Console.ReadLine();
Console.WriteLine("Your last name?");
string studentlast = Console.ReadLine();
Console.WriteLine("And you my child, which house are you from?");
string studentHouse = Console.ReadLine();
Console.WriteLine("And may i know your wizard ID?");
string studentWizID = Console.ReadLine();
Console.WriteLine("And what creature is your lovely Familiar?");
string studentFamiliar = Console.ReadLine();
Console.WriteLine("What is your student ID?");
string babywizID = Console.ReadLine();
Console.WriteLine("sorry this is taking long. Lastly! in School year, what year are you curently in?");
string yearschool = Console.ReadLine();
WizardStudents.Add(new WizardTobe(studentname, studentlast, studentWizID, studentHouse, studentFamiliar, babywizID, yearschool));
I tried to name the object that I want to add to my list as "studentname" which I received with Readline. but I faced another error...
what should I do ? :(
my classes are these:
my parent class
using System;
using System.Collections.Generic;
using System.Text;
namespace HogwartsSignUp
{
public class Wizard
{
string name;
string lastname;
string wizID;
string house;
//teacher
private string yearclass;
private string workID;
//students
private string familiar;
private string studentID;
private string studentyear;
public Wizard(string name, string lastname, string wizID, string house, string familiar, string studentID, string studentyear)
{
this.name = name;
this.lastname = lastname;
this.wizID = wizID;
this.house = house;
this.studentID = studentID;
this.familiar = familiar;
this.studentyear = studentyear;
}
public Wizard(string name, string lastname, string wizID, string house, string yearclass, string workID)
{
this.name = name;
this.lastname = lastname;
this.wizID = wizID;
this.house = house;
this.workID = workID;
this.yearclass = yearclass;
}
public void showStudentInfo()
{
Console.WriteLine("They are a Hogwarts student! Here's the information of them:");
Console.WriteLine("Name: {0} Last name: {1} House: {2} Year: {3} Familiar: {4}", name, lastname,house,studentyear,familiar);
}
public void showTeacherInfo()
{
Console.WriteLine("They are a Hogwarts teacher! Here's the information of them:");
Console.WriteLine("Name:{0} Last Name:{1} House:{2} Teacher of the class: {3}", name, lastname, house, yearclass);
}
}
}
my child class:
using System;
using System.Collections.Generic;
using System.Text;
namespace HogwartsSignUp
{
public class WizardTobe : Wizard
{
string magicwand;
string sportinterest;
string hobby;
public WizardTobe(string name, string lastname, string wizID, string house, string familiar, string studentID, string studentyear) : base (name, lastname, wizID, house, familiar, studentID, studentyear)
{
}
}
}
Use Language Integrated Query to search through the list. Following is the link to the documentation: https://learn.microsoft.com/en-us/dotnet/csharp/linq/
Here is a sample console application using your code that illustrates this.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Console_Example
{
public class WizardTobe
{
public string StudentName { get; set; }
public string StudentLast { get; set; }
public string StudentWizID { get; set; }
public string StudentHouse { get; set; }
public string StudentFamiliar { get; set; }
public string BabyWizID { get; set; }
public string YearsSchool { get; set; }
public WizardTobe(string studentName, string studentLast, string studentWizID, string studentHouse, string studentFamiliar, string babyWizID, string yearsSchool)
{
StudentName = studentName;
StudentLast = studentLast;
StudentWizID = studentWizID;
StudentHouse = studentHouse;
StudentFamiliar = studentFamiliar;
BabyWizID = babyWizID;
YearsSchool = yearsSchool;
}
}
class Program
{
static void Main(string[] args)
{
List<WizardTobe> WizardStudents = new List<WizardTobe>();
string studentname = Console.ReadLine();
Console.WriteLine("Your last name?");
string studentlast = Console.ReadLine();
Console.WriteLine("And you my child, which house are you from?");
string studentHouse = Console.ReadLine();
Console.WriteLine("And may i know your wizard ID?");
string studentWizID = Console.ReadLine();
Console.WriteLine("And what creature is your lovely Familiar?");
string studentFamiliar = Console.ReadLine();
Console.WriteLine("What is your student ID?");
string babywizID = Console.ReadLine();
Console.WriteLine("sorry this is taking long. Lastly! in School year, what year are you curently in?");
string yearschool = Console.ReadLine();
WizardStudents.Add(new WizardTobe(studentname, studentlast, studentWizID, studentHouse, studentFamiliar, babywizID, yearschool));
WizardStudents.Add(new WizardTobe("Peter","","","","","",""));
WizardStudents.Add(new WizardTobe("Steven", "", "", "", "", "", ""));
WizardStudents.Add(new WizardTobe("Maria", "", "", "", "", "", ""));
WizardStudents.Add(new WizardTobe("Ashley", "", "", "", "", "", ""));
string studentToBeSearched = "Ashley";
Console.WriteLine($"\n\nSearching for student named {studentToBeSearched}");
WizardTobe missingStudent = WizardStudents.Where(x => x.StudentName == studentToBeSearched).FirstOrDefault();
Console.WriteLine(missingStudent.StudentName);
Console.WriteLine("Press Any Key");
Console.ReadKey();
}
}
}
Note: Above code is to demonstrate only the solution to the asked problem and not to demonstrate good programming practice.
First of all override ToString() function in your WizardTobe class, return string with all properties you want to print.
public class WizardTobe
{
public string StudentName{ get; set; }
public string StudentLastName{ get; set; }
...
public override string ToString()
{
return $"Student First Name: {StudentName}: Last Name: {StudentLastName}";
}
}
In your program where you want print this information use .Where() or .First() or .Single() as per your requirement.
I am using .Where() as there might be multiple students with same name and lets print all students which satisfy this condition
var results = WizardStudents.Where(s => s.name == somename);
foreach(var result in results)
Console.WriteLine(result);
MSDN :How to override the ToString method
How can I pass e.g 2 strings to Func and return a string?
Let say I would like to pass FirstName and LastName and the result should be like FirstName + LastName;
Moreover, I would like to have a Func declared as a property.
Please take a look at my code:
public class FuncClass
{
private string FirstName = "John";
private string LastName = "Smith";
//TODO: declare FuncModel and pass FirstName and LastName.
}
public class FuncModel
{
public Func<string, string> FunctTest { get; set; }
}
Could you please help me to solve this problem?
This should do the trick:
public class FuncModel
{
//Func syntax goes <input1, input2,...., output>
public Func<string, string, string> FunctTest { get; set; }
}
var funcModel = new FuncModel();
funcModel.FunctTest = (firstName, lastName) => firstName + lastName;
Console.WriteLine(funcModel.FuncTest("John", "Smith"));
I created 3 objects of a class and I want to display on the console how many objects I have created (using a static class variable) - How do I do this ?
I put public static int count = 0; in the class I created but I couldn't get it to increment (count++;) based on how many objects I created of the class. I created the 3 objects in the main method and gave them values for variables.
here is the class I created in my program :
public class Student
{
public static int count = 0;
// count++;
private string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
private string birthDate;
public string BirthDate
{
get { return birthDate; }
set { birthDate = value; }
}
}
In the main method I created 3 objects of class Student:
static void Main(string[] args)
{
// Create 3 students
Student student1 = new Student
{
FirstName = "John",
LastName = "Wayne",
BirthDate = "26/05/1907"
};
Student student2 = new Student
{
FirstName = "Craig",
LastName = "Playstead",
BirthDate ="01/01/1967"
};
Student student3 = new Student
{
FirstName = "Paula",
LastName = "Smith",
BirthDate = "01/12/1977"
};
// Console.WriteLine("The course contains {1} students(s) " studentCounter );
I can't get the counter to ++ based on the way I created the objects.
Increment the count in the constructor:
public class Student
{
public static int count = 0;
public Student()
{
// Thread safe since this is a static property
Interlocked.Increment(ref count);
}
// use properties!
public string FirstName { get; set; }
public string LastName { get; set; }
public string BirthDate { get; set; }
}
You just need a constructor, there you can increment the count.
public Student()
{
count++;
}
You can increment the counter in the constructor
public Student()
{
count++;
}
To print the count variable
we should write some code like below
public static int GetCount()
{
return count;
}
and main class look like :
static void Main(string[] args)
{
// Create 3 students
Student student1 = new Student
{
FirstName = "John",
LastName = "Wayne",
BirthDate = "26/05/1907"
};
Student student2 = new Student
{
FirstName = "Craig",
LastName = "Playstead",
BirthDate ="01/01/1967"
};
Student student3 = new Student
{
FirstName = "Paula",
LastName = "Smith",
BirthDate = "01/12/1977"
};
//To print the count
Console.WriteLine(" Number of Objects is : "+Student.GetCount());
}
and if we have parameterized constructor then we also have to write count++ in that constructor.
Say I have a class like this:
class public Person
{
public string firstName;
public string lastName;
public string address;
public string city;
public string state;
public string zip;
public Person(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
}
And let's further say I create a List of type Person like this:
List<Person> pList = new List<Person>;
pList.Add(new Person("Joe", "Smith");
Now, I want to set the address, city, state, and zip for Joe Smith, but I have already added the object to the list. So, how do I set these member variables, after the object has been added to the list?
Thank you.
You get the item back out of the list and then set it:
pList[0].address = "123 Main St.";
You can keep a reference to your object around. Try adding like this:
List<Person> pList = new List<Person>;
Person p = new Person("Joe", "Smith");
pList.Add(p);
p.address = "Test";
Alternatively you can access it directly through the list.
pList[0].address = "Test";
You can get the first item of the list like so:
Person p = pList[0]; or Person p = pList.First();
Then you can modify it as you wish:
p.firstName = "Jesse";
Also, I would recommend using automatic properties:
class public Person
{
public string firstName { get; set; }
public string lastName { get; set; }
public string address { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
public Person(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
}
You'll get the same result, but the day that you'll want to verify the input or change the way that you set items, it will be much simpler:
class public Person
{
private const int ZIP_CODE_LENGTH = 6;
public string firstName { get; set; }
public string lastName { get; set; }
public string address { get; set; }
public string city { get; set; }
public string state { get; set; }
private string zip_ = null;
public string zip
{
get { return zip_; }
set
{
if (value.Length != ZIP_CODE_LENGTH ) throw new Exception("Invalid zip code.");
zip_ = value;
}
}
public Person(string firstName, string lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}
}
Quite possibly not the best decision to just crash when you set a property here, but you get the general idea of being able to quickly change how an object is set, without having to call a SetZipCode(...); function everywhere. Here is all the magic of encapsulation an OOP.
You can access the item through it's index. If you want to find the last item added then you can use the length - 1 of your list:
List<Person> pList = new List<Person>;
// add a bunch of other items....
// ....
pList.Add(new Person("Joe", "Smith");
pList[pList.Length - 1].address = "....";
Should you have lost track of the element you're looking for in your list, you can always use LINQ to find the element again:
pList.First(person=>person.firstName == "John").lastName = "Doe";
Or if you need to relocate all "Doe"s at once, you can do:
foreach (Person person in pList.Where(p=>p.lastName == "Doe"))
{
person.address = "Niflheim";
}