I am trying to write a C# program using Visual Studio that reads data from a file and allow me perform various sorts on the data. I am a beginner so it took much research to figure out how to write this code: Now I get a:
Format Exception was unhandled. Input string was not in a correct
format
I am not sure where I went wrong. This is happening for the following line of code:
Candidate newrec = new Candidate(str[0], str[1], str [2], str[3], str[4], str[5], str[6], Convert.ToInt32(str[7]), str[8], str[9], str[10], str[11]);
The entire code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Collections;
namespace Unit4IP
{
//used to sort in asceding and descending order
public struct Candidate:IComparable
{
public char[] _FirstName;
public char[] _LastName;
public char[] _Company;
public char[] _Address;
public char[] _City;
public char[] _Country;
public char[] _State;
public char[] _Phone;
public char[] _Fax;
public char[] _Email;
public char[] _Web;
public int _zip;
//for comparing objects
public int CompareTo(object obj)
{
Candidate Candidate2 = (Candidate)obj;
return _LastName.ToString().CompareTo(Candidate2._LastName.ToString());
}
//implements sorting based on assignments such as zip, lastname, etc.
public int CompareTo(Candidate Candidate2,
CandidateComparer.ComparisonType comptype)
{
if(comptype==CandidateComparer.ComparisonType.Lastname)
{
String _LName = new String(_LastName);
String LName = new String(Candidate2._LastName);
return _LName.CompareTo(LName);// Convert Character Array to String because CompareTo Works efficiently with Strings
}
else
{
return Candidate2._zip.CompareTo(_zip); // compareto values that are interchanged in descending order
}
}
//Constructor of Candidate Structure
public Candidate(string FirstName, string LastName, string Company, string Address, string City, string Country, string State, int zip, string Phone, string Fax, string Email, string Web)
{
_FirstName = new char[12];
_LastName = new char[16];
_Company = new char[32];
_Address = new char[32];
_City = new char[24];
_Country = new char[24];
_State = new char[2];
_Phone = new char[12];
_Fax = new char[12];
_Email = new char[32];
_Web = new char[42];
_FirstName = FirstName.ToCharArray();
_LastName = LastName.ToCharArray();
_Company = Company.ToCharArray();
_Address = Address.ToCharArray();
_City = City.ToCharArray();
_Country = Country.ToCharArray();
_State = State.ToCharArray();
_zip = zip;
_Phone = Phone.ToCharArray();
_Fax = Fax.ToCharArray();
_Email = Email.ToCharArray();
_Web = Web.ToCharArray();
}
//Implement IComparer Interface as nested structure
public struct CandidateComparer : IComparer
{
public enum ComparisonType
{ Lastname = 1, zip = 2 }
private ComparisonType _comparisonType;
public ComparisonType comptype
{
get { return _comparisonType; }
set { _comparisonType = value; }
}
public int Compare(object x, object y)
{
Candidate Candidate1 = (Candidate)x;
Candidate Candidate2 = (Candidate)y;
return Candidate1.CompareTo(Candidate2, _comparisonType);
}
}
}
class Program
{
static void Main(string[] args)
{
ArrayList ArrayTest = new ArrayList();
//Loading of File 'ITCO321_U4_sample_data.csv' into ArraList. File only holds values, no heading i.e. remove headings
StreamReader stream1 = File.OpenText("c:\\Users\\Cdhss\\Documents\\ITCO321_U4IP_sample_data-2.csv");
string recdata = null;
while ((recdata = stream1.ReadLine()) != null)
{
string[] str = recdata.Split(',');
Candidate newrec = new Candidate(str[0], str[1], str [2], str[3], str[4], str[5], str[6], Convert.ToInt32(str[7]), str[8], str[9], str[10], str[11]);
ArrayTest.Add(newrec);//add struct object into ArrayList
}
//Traversing of Records
Console.WriteLine("Traversing Records");
foreach (Candidate Candidate1 in ArrayTest)
{
string fname = new String(Candidate1._FirstName);
string lname=new String(Candidate1._LastName);
string company = new String(Candidate1._Company);
string address=new String(Candidate1._Address);
string city=new String(Candidate1._City);
string country = new String(Candidate1._Country);
string phone = new String(Candidate1._Phone);
string fax = new String(Candidate1._Fax);
string email=new String(Candidate1._Email);
string web = new String(Candidate1._Web);
Console.WriteLine( fname + "," + lname + "," + company + "," + address + "," + city + "," + country + "," + Candidate1._zip + "," + phone + "," + fax + "," + email + "," + web);
}
Candidate.CandidateComparer comparer = new Candidate.CandidateComparer();
//Sort by Lastname in ascending order
comparer.comptype = Candidate.CandidateComparer.ComparisonType.Lastname;
ArrayTest.Sort(comparer);
Console.WriteLine("Sorting of Elements by LastName");
foreach (Candidate Candidate1 in ArrayTest)
{
string fname = new String(Candidate1._FirstName);
string lname = new String(Candidate1._LastName);
string company = new String(Candidate1._Company);
Console.WriteLine("\t" + fname + "," + lname + "," + company);
}
// Data sorted in desending order of ZIP field
comparer.comptype = Candidate.CandidateComparer.ComparisonType.zip;
ArrayTest.Sort(comparer);
Console.WriteLine("Sorting of Elements by Zip");
foreach (Candidate Candidate1 in ArrayTest)
{
string fname = new String(Candidate1._FirstName);
string lname = new String(Candidate1._LastName);
string company = new String(Candidate1._Company);
Console.WriteLine("\t" + fname + "," + lname + "," + company + "," + Candidate1._zip);
}
//Display Records of 'NY' State
Console.WriteLine("Display Records of NY State");
foreach (Candidate Candidate1 in ArrayTest)
{
string fname = new String(Candidate1._FirstName);
string lname = new String(Candidate1._LastName);
string company = new String(Candidate1._Company);
string address = new String(Candidate1._Address);
string city = new String(Candidate1._City);
string country = new String(Candidate1._Country);
string phone = new String(Candidate1._Phone);
string fax = new String(Candidate1._Fax);
string email = new String(Candidate1._Email);
string web = new String(Candidate1._Web);
if (new String(Candidate1._State).Contains("NY"))
Console.WriteLine(fname + "," + lname + "," + company + "," + address + "," + city + "," + country + "," + Candidate1._zip + "," + phone + "," + fax + "," + email + "," + web);
}
Console.Read();
}
}
}
Your problem is in your call to Convert.ToInt32. Whatever string you are passing can't be parsed as an int.
A good solution here might be to use the some structured exception handling, either with try catch blocks or Int32.TryParse(string) for example you could do this
int intValue;
if (Int32.TryParse(str[7], out intValue))
{
//Do some thing with the int value
}
else
{
throw new Exception("Some informative error message, probably using string.Format to include the string you tried to parse");
}
TryParse returns true if the parse is successfull, false if it is not, and puts the parsed integer value in the second out parameter.
A few other comments on you code to help you out.
No one uses ArrayLists in C# anymore. Generics were introduced a long time ago, and it is almost always better, from a standpoint of both type safety and speed to use a List (Look up C# generics if you don't know what they are).
You don't need to copy the candidate properties in your foreach loop into new variables.
Give more informative variable names. Readability is the single most important quality in good code. fname should be firstName, recdata should be recievedData. Key strokes are cheap in a world with tab completion.
Related
I have an API that loops through addresses and cleanses them. I am testing it with about 40k addresses, and it takes several hours to loop through thousands of them. Sometimes it throws an error and closes out the application and I have to start it over. Is there a way that I can write in error handling into the catch, that if there is an error, it will just log it, but continue running the app?
I am using VS 2019, C#, Windows Forms.
public class Elements
{
public string streetaddress1 { get; set; }
public string streetaddress2 { get; set; }
public string city { get; set; }
public string state { get; set; }
public string zip { get; set; }
public string country { get; set; }
}
void Output(string strDebugText)
{
try
{
System.Diagnostics.Debug.Write(strDebugText + Environment.NewLine);
txtResponse.Text = txtResponse.Text + strDebugText + Environment.NewLine;
txtResponse.SelectionStart = txtResponse.TextLength;
txtResponse.ScrollToCaret();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex.Message, ToString() + Environment.NewLine);
}
}
private void btnMultiple_Click(object sender, EventArgs e)
{
//Loads address that need to be cleansed
string filePath = #"C:data.csv";
List<Elements> addresses = new List<Elements>();
List<string> lines = File.ReadAllLines(filePath).ToList();
foreach (var line in lines)
{
string[] entries = line.Split(',');
Elements newElement = new Elements();
newElement.streetaddress1 = entries[0];
newElement.streetaddress2 = entries[1];
newElement.city = entries[2];
newElement.state = entries[3];
newElement.zip = entries[4];
addresses.Add(newElement);
}
foreach (var Element in addresses)
{
Output($"{ Element.streetaddress1 } { Element.city} { Element.state } { Element.zip } " +
$"{ Element.country }");
var venvMulti = new AreaLookup.VertexEnvelope();
var clientMulti = new AreaLookup.LookupTaxAreasWS90Client();
var reqMulti = new AreaLookup.TaxAreaRequestType();
var reqresMulti = new AreaLookup.TaxAreaResultType();
var resMulti = new AreaLookup.TaxAreaResponseType();
string inputXMLMulti;
string outputXMLMulti;
var TALMulti = new AreaLookup.TaxAreaLookupType();
var TALasofDateMulti = new DateTime();
var resTypeMulti = new AreaLookup.TaxAreaLookupResultType();
var postalMulti = new AreaLookup.PostalAddressType();
string StrNoteMulti = "";
int i, y;
var x = default(int);
postalMulti.MainDivision = Element.state;
postalMulti.City = Element.city;
postalMulti.PostalCode = Element.zip;
postalMulti.StreetAddress1 = Element.streetaddress1;
TALasofDateMulti = Conversions.ToDate("2020-12-11");
TALMulti.asOfDate = TALasofDateMulti;
TALMulti.Item = postalMulti;
reqMulti.TaxAreaLookup = TALMulti;
var LITMulti = new AreaLookup.LoginType();
venvMulti.Login = new AreaLookup.LoginType();
venvMulti.Login.UserName = "****";
venvMulti.Login.Password = "****";
venvMulti.Item = reqMulti;
inputXMLMulti = (string)SerializeObjectToString(venvMulti);
Output(inputXMLMulti);
try
{
clientMulti.LookupTaxAreas90(ref venvMulti);
resMulti = (AreaLookup.TaxAreaResponseType)venvMulti.Item;
outputXMLMulti = (string)SerializeObjectToString(venvMulti);
Output(outputXMLMulti);
var loopTo = resMulti.TaxAreaResult.Length - 1;
}
catch (NullReferenceException)
{
Console.WriteLine("Null");
}
reqMulti = default;
reqresMulti = default;
resMulti = default;
void debugOutputCleansedMulti(string strDebugTextCleansedMulti)
{
try
{
System.Diagnostics.Debug.Write(strDebugTextCleansedMulti + Environment.NewLine);
txtCleansed.Text = txtCleansed.Text + strDebugTextCleansedMulti + Environment.NewLine;
txtCleansed.SelectionStart = txtCleansed.TextLength;
txtCleansed.ScrollToCaret();
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex.Message, ToString() + Environment.NewLine);
}
}
debugOutputCleansedMulti("Address Cleanse Started: ");
var venvCleansedMulti = new AreaLookup.VertexEnvelope();
var clientCleansedMulti = new AreaLookup.LookupTaxAreasWS90Client();
var reqCleansedMulti = new AreaLookup.TaxAreaRequestType();
var reqresCleansedMulti = new AreaLookup.TaxAreaResultType();
var resCleansedMulti = new AreaLookup.TaxAreaResponseType();
string inputXMLCleansedMulti;
string outputXMLCleansedMulti;
var TALCleansedMulti = new AreaLookup.TaxAreaLookupType();
var TALasofDateCleansedMulti = new DateTime();
var resTypeCleansedMulti = new AreaLookup.TaxAreaLookupResultType();
var postalCleansedMulti = new AreaLookup.PostalAddressType();
string StrNoteCleansedMulti = "";
int a, b;
var c = default(int);
postalCleansedMulti.MainDivision = Element.state;
postalCleansedMulti.City = Element.city;
postalCleansedMulti.PostalCode = Element.zip;
postalCleansedMulti.StreetAddress1 = Element.streetaddress1;
TALasofDateCleansedMulti = Conversions.ToDate("2020-12-11");
TALCleansedMulti.asOfDate = TALasofDateCleansedMulti;
TALCleansedMulti.Item = postalCleansedMulti;
reqCleansedMulti.TaxAreaLookup = TALCleansedMulti;
var LITCleansedMulti = new AreaLookup.LoginType();
venvCleansedMulti.Login = new AreaLookup.LoginType();
venvCleansedMulti.Login.UserName = "****";
venvCleansedMulti.Login.Password = "****";
venvCleansedMulti.Item = reqCleansedMulti;
int j = 1;
//inputXMLCleansed = resCleansed.TaxAreaResult[0].PostalAddress[0].StreetAddress1 + " - " + resCleansed.TaxAreaResult[0].PostalAddress[0].PostalCode + " - " + resCleansed.TaxAreaResult[0].confidenceIndicator;
//debugOutputCleansed(inputXMLCleansed);
try
{
clientCleansedMulti.LookupTaxAreas90(ref venvCleansedMulti);
resCleansedMulti = (AreaLookup.TaxAreaResponseType)venvCleansedMulti.Item;
debugOutputCleansedMulti(resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress1 + " | Street Address 1" + Environment.NewLine +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress2 + " | Street Address 2" + Environment.NewLine +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].SubDivision + " | County" + Environment.NewLine +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].City + " | City" + Environment.NewLine +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].PostalCode + " | Zip Code" + Environment.NewLine +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].MainDivision + " | State" + Environment.NewLine +
resCleansedMulti.TaxAreaResult[0].confidenceIndicator + " | Confidence Indicator");
string pathCleansed = #"C:\dev\data\data.csv";
string[] createText = {
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress1 + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].StreetAddress2 + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].City + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].MainDivision + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].PostalCode + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].Country + "," +
resCleansedMulti.TaxAreaResult[0].PostalAddress[0].SubDivision + "," +
resCleansedMulti.TaxAreaResult[0].confidenceIndicator
};
File.AppendAllLines(pathCleansed, createText, System.Text.Encoding.UTF8);
txtCounter.Text = j.ToString();
j++;
var loopTo = resCleansedMulti.TaxAreaResult.Length - 1;
for (b = 0; b <= loopTo; b++)
{
if (c == 0)
{
StrNoteCleansedMulti = resCleansedMulti.TaxAreaResult[b].PostalAddress[0].StreetAddress1 + " - " + resCleansedMulti.TaxAreaResult[b].confidenceIndicator; c = 1;
}
else
{
StrNoteCleansedMulti += ", " + resCleansedMulti.TaxAreaResult[b].taxAreaId + " - " + resMulti.TaxAreaResult[b].confidenceIndicator;
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex.Message, ToString() + Environment.NewLine);
}
reqCleansedMulti = default;
reqresCleansedMulti = default;
resCleansedMulti = default;
}
}
Essentially you need a way to save your work in progress. One pattern would be to load the file and store it in a database, then as you process each line you mark off which item you have processed. If you did this I would split the code into different modules, importing file, processing file, and exporting results.
Another simpler approach might be to write the results out as you process them, and record the line number from the input file. Then if you have to restart, find the last line you output and use that to skip reprocessing the items in your input file
how to post currency code as United States dollar and India. By default it uses IND.
[HttpPost]
public void Plans(UserRegistreModel model)
{
string firstName = model.FirstName;
string middleName = model.MiddleName;
string lastName = model.LastName;
string amount = Convert.ToString(model.Amount);
string Noofemp = model.NoOfEmployees;
string productInfo = "HRMS";
string email = model.Email;
string phone = model.Contact;
string FirmName = model.FirmName;
//string surl = form["txtsurl"].ToString();
//string furl = form["txtfurl"].ToString();
RemotePost myremotepost = new RemotePost();
string key = "";
string salt = "";
//posting all the parameters required for integration.
myremotepost.Url = "https://secure.payu.in/_payment";
myremotepost.Add("key", "");
string txnid = Generatetxnid();
myremotepost.Add("txnid", txnid);
myremotepost.Add("amount", amount);
myremotepost.Add("productinfo", productInfo);
myremotepost.Add("firstname", firstName);
myremotepost.Add("phone", phone);
myremotepost.Add("email", email);
//UserRegistreModel register = new UserRegistreModel();
TempData["model"] = model;
myremotepost.Add("surl", "");
myremotepost.Add("furl", "");
string hashString = key + "|" + txnid + "|" + amount + "|" + productInfo + "|" + firstName + "|" + email + "|||||||||||" + salt;
string hash = Generatehash512(hashString);
myremotepost.Add("hash", hash);
myremotepost.Post();
}
You can do things like this
myremotepost.Add("currency", "INR");
It will set the currency INR for current request.
I'm currently working on finding a way to Log UserActions/Requests. I'm inclined towards logging the details to a text file. The LOG details are organized in a tree-like (hierarchical) structure so that it is readable and shows method names in a step-by-step manner. (if a request went through several methods)
I have a sample app which works fine but it is not the way how it should be. Consider the following classes.
Node class which is the template to make a tree-like (hierarchical) structure. It has attributes such as name (method name), Time and a List type para named Children.
public class Node
{
public string Name; // method name
public DateTime Time; // time when accessed
public List<Node> Children;
public static void PrintTree(Node tree)
{
string temp = "";
List<Node> firstStack = new List<Node>();
firstStack.Add(tree);
List<List<Node>> childListStack = new List<List<Node>>();
childListStack.Add(firstStack);
while (childListStack.Count > 0)
{
List<Node> childStack = childListStack[childListStack.Count - 1];
if (childStack.Count == 0)
{
childListStack.RemoveAt(childListStack.Count - 1);
}
else
{
tree = childStack[0];
childStack.RemoveAt(0);
string indent = "";
for (int i = 0; i < childListStack.Count - 1; i++)
{
indent += (childListStack[i].Count > 0) ? "| " : " ";
}
temp = indent + "+- " + tree.Name + " (" + tree.Time + ")";
Console.WriteLine(indent + "+- " + tree.Name + " (" + tree.Time + ")");
File.AppendAllText(#"C:\Users\aimalkhan\Desktop\Log Work\Log.txt", temp + Environment.NewLine);
if (tree.Children != null)
{
if (tree.Children.Count > 0)
{
childListStack.Add(new List<Node>(tree.Children));
}
}
}
}
File.AppendAllText(#"C:\Users\aimalkhan\Desktop\Log Work\Log.txt", Environment.NewLine + "*************************************************************" + Environment.NewLine);
}
}
My sample Employee class with a sample method SetEmployeeName() having AN EXTRA parameter of NODE type for Logging purposes.
public class Employee
{
private string FirstName { get; set; }
private string LastName { get; set; }
public string SetEmployeeName(string firstName, string lastName, Node node)
{
node.Name = "Class Name: " +this.GetType().Name + ", Calling method Name: setEmployeeName()";
node.Time = DateTime.Now;
this.FirstName = firstName;
this.LastName = lastName;
return this.FirstName + " " + this.LastName;
}
public void CompleteTask(string empName, string taskName)
{
Console.WriteLine("Employee: " + empName + " is completing the task: " + taskName);
}
}
and finally this is how i'm using the aforementioned sample of Codes.
Node root = new Node();
root.Name = "ClassName: Main";
root.Time = DateTime.Now;
root.Children = new List<Node>();
Node child = new Node();
Employee emp = new Employee();
emp.SetEmployeeName("John", "D", child);
root.Children.Add(child);
Node.PrintTree(root);
This is how the output looks
Now my question is that it would really be a headache for me to pass a NODE type para every time i need a child info log. Could this be some how made centralized in any possible way? Is there a better way than this one? A little guidance would really be appreciated.
I have the following code that inputs a CSV file and then converts it and outputs a CSV file. I am using FileHelper for CSV reading. I am having a couple problems with it. First, an extra line with field information is being inserted (see below). The second problem is that I have added double quotes so I can have a string in a cell that contains a comma; I can't find anything wrong with the formatting but it will not import into excel and only shows the double quotes and the first item. I have tried using the double quotation mark for escaping text option when importing into excel. The third problem is that some fields are blank and result in later offset of fields.
Second line of fields:
, base, 0, 0, 0, Product Name, Size, Brand, Gender, Type, SKU, Stock, Sí, "Photo1, Photo2, Photo3", Photo1, Photo1, Photo1
Code:
using System;
using FileHelpers;
using System.IO;
[DelimitedRecord(";")]
public sealed class StoreItems
{
[FieldOptional()]
public String Attribut;
[FieldOptional()]
public String ProductName;
[FieldOptional()]
public String Size;
[FieldOptional()]
public String Brand;
[FieldOptional()]
public String Type;
[FieldOptional()]
public String ParentSKU;
[FieldOptional()]
public String SKU;
[FieldOptional()]
public String Stock;
[FieldOptional()]
public String RetailEURO;
[FieldOptional()]
public String SuggestedsellEURO;
[FieldOptional()]
public String Weight;
[FieldOptional()]
public String Description;
[FieldOptional()]
public String Photo1;
[FieldOptional()]
public String Photo2;
[FieldOptional()]
public String Photo3;
[FieldOptional()]
public String Gender;
[FieldOptional()]
public String EAN13;
}
public class RunProgram
{
public static void Main()
{
FileHelperEngine engine = new FileHelperEngine(typeof(StoreItems));
StoreItems[] res = engine.ReadFile("Presta.csv") as StoreItems[];
Directory.CreateDirectory("Output");
StreamWriter sw = new StreamWriter(#".\Output\" + DateTime.Now.ToString("hhmmss") + ".csv");
sw.AutoFlush = true;
Console.SetOut(sw);
Console.WriteLine("_type, _product_websites, tax_class_id, _visibility, is_in_stock, name, taglia, manufacturer, gender, _attribute_set, sku, qty, use_external_images, external_gallery, " +
"thumbnail_external_url, small_image_external_url, image_external_url");
foreach(StoreItems item in res)
{
string newtype = null;
int visibility = 0;
if (item.Attribut == "Parent")
{
newtype = "Configurable";
visibility = 4;
}
else if (item.Attribut == "Child")
{
newtype = "Simple";
visibility = 1;
}
int isinstock;
int stockint;
try
{
stockint = Convert.ToInt32(item.Stock);
}
catch
{
stockint = 0;
}
if (stockint > 0)
{
isinstock = 1;
}
else
{
isinstock = 0;
}
Console.WriteLine(newtype + ", base, 0, " + visibility + ", " + isinstock + ", " + item.ProductName + ", " + item.Size + ", " +
item.Brand + ", " + item.Gender + ", " + item.Type + ", " + item.SKU + ", " + item.Stock + ", Sí, " + #""""+item.Photo1+ ", "+item.Photo2+", "+item.Photo3+#"""" + ", " + item.Photo1 + ", " + item.Photo1 +
", " + item.Photo1);
}
}
}
Edit: I just realized that the second line is being added in from the reading of the input file. I just need to find a way to ignore the first line. The fields also no longer seem to be offsetting. Now just how to use commas in the csv?
Second problem;
You don't have to use commas as a separator, you can use any character you want. So as a quick fix, why not change the ',' separator in your output to '|'.
If, of course, you also need to output '|' in your text, this is not going to help, but if not - quick fix to get you going.
One problem; you have;
string newtype = null;
int visibility = 0;
if (item.Attribut == "Parent")
{
newtype = "Configurable";
visibility = 4;
}
else if (item.Attribut == "Child")
{
newtype = "Simple";
visibility = 1;
}
If item.Attribut is neither "Parent" or "Child" exactly, then newtype is not set. Hence why the first field in your example output is blank.
I have a method which gets the values of the properties of an object and appends some commas to it. I want to make this generinc so i can use it with other objects.
foreach (var row in rows.ToList())
{
sbResult.Append(
delimiter + row.MediaName + delimiter + separator +
delimiter + row.CountryName + delimiter + separator +
delimiter + row.ItemOverRideDate + delimiter + separator +
delimiter + row.Rating + delimiter + separator +
delimiter + row.BatchNo + delimiter + separator +
delimiter + row.NoInBatch + delimiter + separator +
delimiter + row.BatchDate + delimiter + separator +
delimiter + row.DataType + delimiter + separator +
delimiter + row.ByLine + delimiter + separator +
delimiter + row.IssueNo + delimiter + separator +
delimiter + row.Issue + delimiter + separator +
delimiter + row.MessageNo + delimiter + separator +
delimiter + row.Message + delimiter + separator +
delimiter + row.SourceName + delimiter + separator +
delimiter + row.SourceType + delimiter + separator);
//end of each row
sbResult.AppendLine();
}
I have tried using var rowData = row.GetType().GetProperties(); but it only returns the property itself and I dont know how to get the value of the property.
Since Type.GetProperties returns a collection of PropertyInfo, you follow that up by calling PropertyInfo.GetValue. Here's how you can do that (and all the rest together) with LINQ:
var line = string.Join(
row.GetType().GetProperties()
.Select(pi => pi.GetValue(row))
.Select(v => delimiter + v.ToString() + delimiter),
separator);
However, you might want to reconsider your approach. This code will break if GetProperties fetches static properties or indexers along with "normal" properties; it also requires that the code be run with full trust (otherwise no reflection is possible). And finally, it's going to be slow because a) reflection is inherently slow and b) it will keep reflecting on the same things over and over again without caching any of the information it has already discovered.
In addition to the above potential problems, if there is even a remote chance that you will later want to filter what gets printed out it is probably better to encapsulate this logic inside a (virtual?) method on row and just do something like
sbResult.AppendLine(row.SerializeAsLine());
You can use something like this to iterate over all the properties of a particular type:
public static IEnumerable<KeyValuePair<string, T>> PropertiesOfType<T>(object obj)
{
return from p in obj.GetType().GetProperties()
where p.PropertyType == typeof(T)
select new KeyValuePair<string, T>(p.Name, (T)p.GetValue(obj));
}
Then you could specify the type as string for all your string properties.
Compilable sample:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
private static void Main()
{
var test = new Test
{
Str1 = "S1",
Str2 = "S2",
Str3 = "S3",
Str4 = "S4"
};
foreach (var property in PropertiesOfType<string>(test))
{
Console.WriteLine(property.Key + ": " + property.Value);
}
}
public static IEnumerable<KeyValuePair<string, T>> PropertiesOfType<T>(object obj)
{
return from p in obj.GetType().GetProperties()
where p.PropertyType == typeof(T)
select new KeyValuePair<string, T>(p.Name, (T)p.GetValue(obj));
}
}
public class Test
{
public string Str1 { get; set; }
public string Str2 { get; set; }
public string Str3 { get; set; }
public string Str4 { get; set; }
}
}
Here it is.
List<PropertyInfo> _propInfo = _row.GetType().GetProperties();
foreach (var item in _propInfo)
{
object _value = item.GetValue(_row, null);
if (_value != null)
{
// Save the Value
}
}
GetProperties returns an array of PropertyInfo, so use the GetValue method and use your object as it's input to get the value for each property. Here is the code:
public class MyClass
{
public string MyProperty1 { get; set; }
public string MyProperty2 { get; set; }
public string MyProperty3 { get; set; }
}
Then
MyClass myObj = new MyClass() { MyProperty1 = "first", MyProperty2 = "second", MyProperty3 = "third" };
List<string> array = new List<string>();
foreach (var item in typeof(MyClass).GetProperties())
{
array.Add(item.GetValue(myObj, null).ToString());
}
var result = string.Join(",", array); //use your own delimiter
var values = instance
.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Select(z => string.Format("{0}: {1}\n", z.Name, z.GetValue(instance, null)));
string res = string.Concat(values);
Where instance is the instance of your object. You might want to avoid LINQ and use a loop if StringBuilder is required (depending on the number of properties).