Reading Generic Value from List of Generic Objects - c#

I am trying to loop through a list of generic objects call Condition<T> to read the generic field Value. I followed this question to be able to store the List<Condition<T>>. The issue I am running into now is that I can't use the Value field in my loop. What do I need to change in order to use the Value field?
Main
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal))
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual))
foreach (ConditionBase c in Conditions)
{
if (c.GetType() == typeof(string))
{
// c.Value throws an error
url += c.Field + " " + c.ConditionOperator + " '" + c.Value + "' and ";
}
else if (c.GetType() == typeof(DateTime))
{
// c.Value throws an error
url += c.Field + " " + c.ConditionOperator + " " + Helpers.FormatDate(c.Value) + " and ";
}
}
Condition Base
public interface ConditionBase
{
Field Field { get; set; }
ConditionOperator ConditionOperator { get; set; }
}
Condition
public class Condition<T> : ConditionBase
{
private Field _Field;
private T _Value;
private ConditionOperator _ConditionOperator;
public Condition(Field field, T value, ConditionOperator condition)
{
this._Field = field;
this._Value = value;
this._ConditionOperator = condition;
}
public Field Field
{
get
{
return this._Field;
}
set
{
if (this._Field != value)
{
this._Field = value;
}
}
}
public T Value
{
get
{
return this._Value;
}
set
{
if (!EqualityComparer<T>.Default.Equals(this._Value, value))
{
this._Value = value;
}
}
}
public ConditionOperator ConditionOperator
{
get
{
return this._ConditionOperator;
}
set
{
if (this._ConditionOperator != value)
{
this._ConditionOperator = value;
}
}
}
}
Enums
public enum Field{
Field1,
Field2
}
public enum ConditionOperator{
Equal,
NotEqual,
GreaterThan,
LessThan
}
Solution
This solution is based on the comments by #orhtej2 & the answer by #Igor.
Main - Test
static void Main(string[] args)
{
var x1 = new Condition<int>(new Field(), 123, ConditionOperator.Equal);
var x2 = new Condition<string>(new Field(), "test", ConditionOperator.Equal);
var x3 = new Condition<DateTime>(new Field(), new DateTime(2018,5,5), ConditionOperator.Equal);
var qqq = new List<ConditionBase>();
qqq.Add(x1);
qqq.Add(x2);
qqq.Add(x3);
foreach (ConditionBase c in qqq)
{
Console.WriteLine(c.GetValue());
}
Console.ReadLine();
}
Condition Base
public interface ConditionBase
{
Field Field { get; set; }
ConditionOperator ConditionOperator { get; set; }
string GetValue();
}
Condition
public class Condition<T> : ConditionBase
{
private Field _Field;
private T _Value;
private ConditionOperator _ConditionOperator;
public Condition(Field field, T value, ConditionOperator condition)
{
this._Field = field;
this._Value = value;
this._ConditionOperator = condition;
}
public Field Field
{
get
{
return this._Field;
}
set
{
if (this._Field != value)
{
this._Field = value;
}
}
}
public T Value
{
get
{
return this._Value;
}
set
{
if (!EqualityComparer<T>.Default.Equals(this._Value, value))
{
this._Value = value;
}
}
}
public ConditionOperator ConditionOperator
{
get
{
return this._ConditionOperator;
}
set
{
if (this._ConditionOperator != value)
{
this._ConditionOperator = value;
}
}
}
public string GetValue()
{
if (Value is string)
{
return "'" + Value.ToString() + "'";
}
else if (Value is DateTime)
{
return Helpers.FormatDate(Convert.ToDateTime(Value));
}
else
{
return Value.ToString();
}
}
}
Enums
public enum Field{
Field1,
Field2
}
public enum ConditionOperator{
Equal,
NotEqual,
GreaterThan,
LessThan
}

You have syntax errors in the code like the lacking public scope of your enums and ConditionOperator.Equal (not ConditionOperator.Equals) but that asside here is the fix.
Conditions should be of type List<ConditionBase>
Use OfType on the List to retrieve and cast the resulting type to Condition<string>. I assume that this was your intention with your added check c.GetType() == typeof(string)
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual));
foreach (var c in Conditions.OfType<Condition<string>>())
{
url += c.Field + " " + c.ConditionOperator + " '" + c.Value + "' and ";
}
If you want a generic property that you can access on all instances regardless of the generic type constraint then you would need to extend the base interface accordingly.
public interface ConditionBase
{
Field Field { get; set; }
ConditionOperator ConditionOperator { get; set; }
object FieldValue { get; }
}
public class Condition<T> : ConditionBase
{
/* I only included the added code in this type */
public object FieldValue
{
get { return (object) this.Value; }
}
}
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual));
foreach (var c in Conditions)
{
url += c.Field + " " + c.ConditionOperator + " '" + c.FieldValue + "' and ";
}
It seems you want to output your value to a string based on the changes in your question. Add a string formatter to your type.
/* I only included the added code in this type */
public class Condition<T> : ConditionBase
{
private Func<T, string> _formatValue;
public Condition(Field field, T value, ConditionOperator condition, Func<T, string> formatValue)
{
this._Field = field;
this._Value = value;
this._ConditionOperator = condition;
this._formatValue = formatValue;
}
public override string ToString()
{
return this._formatValue(this.Value);
}
}
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal, (val)=> val.ToString()));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual, (val)=> val));
foreach (var c in Conditions)
{
url += c.Field + " " + c.ConditionOperator + " '" + c.ToString() + "' and ";
}

Related

C# Iterate through nested properties using IEnumerator

I have seen examples (and official ones) for IEnumerator on lists and arrays or dicts, but I have a different problem. I have classes with properties, how may I implement the IEnumerable and IEnumerator in that case?
My properties classes are:
public class standardMessage
{
public messageProperties message { get; set; }
public messageFlag flag { get; set; }
}
public class messageProperties
{
public string messageSubject { get; set; }
public string messageBody { get; set; }
}
public class messageFlag
{
public Boolean flagImportant { get; set; }
public Boolean flagPersonal { get; set; }
}
And this is the Program:
public class Program
{
static void Main(string[] args)
{
standardMessage myMessage = new standardMessage();
myMessage.message = new messageProperties
{
messageSubject = "Greetings",
messageBody = "Happy Weekend"
};
myMessage.flag = new messageFlag
{
flagImportant = false,
flagPersonal = true
};
//how do I iterate through all properties, without knowing how many are there, instead of writing this worm line of code?
Console.WriteLine(myMessage.message.messageSubject.ToString() + "\r\n" + myMessage.message.messageBody.ToString() + "\r\n" + myMessage.flag.flagImportant.ToString() + "\r\n" + myMessage.flag.flagPersonal.ToString());
Console.ReadLine();
}
}
If you want a production-grade way of printing your objects as a formatted string, you need to go and override ToString in all your classes to return whatever format you want.
However, if you just want to print the things on screen for debugging or logging purposes, why not JSON?
public static string ToJson(object #object) =>
System.Text.Json.JsonSerializer.Serialize(#object, new JsonSerializerOptions{WriteIndented = true});
Console.WriteLine(ToJson(myMessage));
Prints
{
"message": {
"messageSubject": "Greetings",
"messageBody": "Happy Weekend"
},
"flag": {
"flagImportant": false,
"flagPersonal": true
}
}
Quick and dirty, but quick and working.
I made a very primitive object to json converter. I wouldn't use this in production and it's about 30% slower than Newtonsoft but it get's the job done.
private static string PrintObject(object obj, int depth = 1)
{
var type = obj.GetType();
if (type.IsPrimitive || type == typeof(Decimal) || type == typeof(String))
return "\"" + obj.ToString() + "\"";
var props = type.GetProperties();
string ret = "";
for (var i = 0; i < props.Length; i++)
{
var val = props[i].GetValue(obj);
ret += new string('\t', depth) + "\"" + props[i].Name + "\":" + PrintObject(val, depth + 1);
if (i != props.Length - 1)
ret += "," + Environment.NewLine;
}
return ("{" + Environment.NewLine + ret + Environment.NewLine + new string('\t', depth - 1) + "}").Replace("\t", " ");
}
Gives the result
{
"message":{
"messageSubject":"Greetings",
"messageBody":"Happy Weekend"
},
"flag":{
"flagImportant":"False",
"flagPersonal":"True"
}
}

sort text file by property (e.g. .last_name)

I've searched StackOverflow for an answer to this, but can't find a clear answer.
I've this Player Class (Yes i've posted the class before)
namespace Tennis_Match
{
class Player
{
private string first_name;
private string middle_name;
private string last_name;
private DateTime dob;
private string nat;
private char gender;
public string First_name { get { return first_name; } set { first_name = value; } }
public string Middle_name { get {return middle_name; } set { middle_name = value; } }
public string Last_name { get { return last_name; } set { last_name = value; } }
public DateTime Dob { get { return dob; } set { dob = value; } }
public string Nat { get { return nat; } set { nat = value; } }
public char Gender { get { return gender; } set { gender = value; } }
public Player(string first_name, string last_name, string middle_name, DateTime dob, string nat, char gender)
{
this.first_name = first_name;
this.last_name = last_name;
this.middle_name = middle_name;
this.dob = dob;
this.nat = nat;
this.gender = gender;
}
public override string ToString()
{
return first_name + " " + middle_name + " " + last_name + " " + dob + " "+ nat + " " + gender;
}
public static int CalculateAge(DateTime dob)
{
int years = DateTime.Now.Year - dob.Year;
if ((dob.Month > DateTime.Now.Month) || (dob.Month == DateTime.Now.Month && dob.Day > DateTime.Now.Day))
years--;
return years;
}
private List<string> content = new List<string>();
public string FileName { get; set; }
public string Delimiter { get; set; }
private void Load()
{
TextFieldParser par = new TextFieldParser(FileName);
par.TextFieldType = FieldType.Delimited;
par.SetDelimiters(Delimiter);
while (!par.EndOfData)
{
string[] fields = par.ReadFields();
foreach (string field in fields)
{
Console.WriteLine(field);
}
}
par.Close();
}
public void RunReadCSVFile(string fn, string delim = "|")
{
FileName = fn;
Delimiter = delim;
Load();
}
public string GetLine(string fileName, int line)
{
using (var sr = new StreamReader(fileName))
{
for (int i = 1; i < line; i++)
sr.ReadLine();
return sr.ReadLine();
}
}
}
}
Then I've another class tournament. I want to sort a textfile by among other Last_name. I've got an idea that i might need to use IComparable to sort the file.
The file is structured like this:
1|Mariuss|Luka|Thygesen|1986-07-25|NAURU|NR
First you have nothing to sort. So add to class
static List<Player> players = new List<Player>();
Next you need to add items to List in following function
private void Load()
{
TextFieldParser par = new TextFieldParser(FileName);
par.TextFieldType = FieldType.Delimited;
par.SetDelimiters(Delimiter);
while (!par.EndOfData)
{
string[] fields = par.ReadFields();
foreach (string field in fields)
{
Console.WriteLine(field);
}
//-----------------------------Add -----------------------
Player newPlayer = new Player(fields[0], fields[1], fields[2], DateTime.Parse(fields[3]), fields[4], fields[5][0]);
players.Add(newPlayer);
}
par.Close();
}
Now you have something to sort. So add a sort method (or CompareTo())
public void Sort()
{
players = players.OrderBy(x => new { x.last_name, x.first_name, x.middle_name }).ToList();
}

How to use a changed value (C# / WCF)

So I need to create this bank service. I have everything except I am trying to use the updated balance from a customer after a transaction such a withdraw or deposit. For example the customer starts off with $1000, and customer 1 deposits $300. The updated balance should be $1300, but once I do another transaction it goes back to the default $1000, instead of the new balance of $1300. The customers are in a list.
[ServiceContract(SessionMode=SessionMode.Allowed)]
public interface IBankService
{
[OperationContract]
string GetCustDetails(int act);
[OperationContract]
string WithdrawMoney(int act, double amt);
[OperationContract]
string DepositMoney(int act,double amt);
[OperationContract]
string ViewBalance(int act);
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
[DataContract]
public class Customer
{
private int accountNumber; private double viewBalance, depositMoney;
private string customerName, customerAddress;
public Customer(int act, string str_name, string adrs, double bal)
{
accountNumber = act;
customerName = str_name;
customerAddress = adrs;
viewBalance = bal;
}
[DataMember(Name = "Name")]
public string CustomerName
{
get { return customerName; }
set { customerName = value; }
}
[DataMember(Name = "Address")]
public string CustomerAddress
{
get { return customerAddress; }
set { customerAddress = value; }
}
[DataMember(Name = "Account")]
public int AccountNumber
{
get { return accountNumber; }
set { accountNumber = value; }
}
[DataMember(Name = "Balance", EmitDefaultValue = true)]
public double ViewBalance
{
get { return viewBalance; }
set
{
if (value <= 0.0)
viewBalance = 0.0;
else
viewBalance = value;
}
}
[DataMember(Name = "Credit")]
public double DepositMoney
{
get { return depositMoney; }
set { depositMoney = value; }
}
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
class BankService : IBankService
{
List<Customer> custList;
static double balance1 = 1000;
static double balance2 = 1000;
static double balance3 = 1000;
static double balance4 = 1000;
static double balance5 = 1000;
public BankService()
{
custList = new List<Customer>();
custList.Add(new Customer(100, "Jack", "404 Bay Avenue", balance1));
custList.Add(new Customer(200, "Jeff", "255 Wade Avenue",balance2));
custList.Add(new Customer(300, "Lou", "984 Leslie Road", balance3));
custList.Add(new Customer(400, "Johnson","1080 Queen Street", balance4));
custList.Add(new Customer(500, "Alex","777 Jane Street", balance5));
}
public string GetCustDetails(int act)
{
foreach (Customer cust in custList)
{
if (cust.AccountNumber == act)
{
return string.Format("Account Number: " + cust.AccountNumber + "\n" +
"Name: " + cust.CustomerName + "\n" +
"Address: " + cust.CustomerAddress + "\n" +
"Balance: $" + cust.ViewBalance);
}
} // end foreach
return string.Format("{0}", "Customer does not exists!");
}
//public string DepositMoney(int act, double amt)
//{
// string balance = null;
// foreach (Customer cust in custList)
// {
// if (cust.AccountNumber == act)
// {
// bal = bal + Dep;
// }
// }
// return balance;
//}
public string DepositMoney(int act, double amt)
{
foreach (Customer cust in custList)
{
if (cust.AccountNumber == act)
{
cust.ViewBalance = cust.ViewBalance + amt;
return string.Format("Account Number : " + cust.AccountNumber + "\n" +
"Name : " + cust.CustomerName + "\n" +
"Address : " + cust.CustomerAddress + "\n" +
"Balance :$ " + cust.ViewBalance);
}
}
return string.Format("{0}", "Customer does not exists!");
}
//public double WithdrawMoney(double widraw)
//{
// return bal = bal - widraw;
//}
// public double ViewBalance(int act)
//{
// return bal;
//}
public string WithdrawMoney(int act, double amt)
{
foreach (Customer cust in custList)
{
if (cust.AccountNumber == act)
{
cust.ViewBalance = cust.ViewBalance - amt;
return string.Format("Account Number : " + cust.AccountNumber + "\n" +
"Name : " + cust.CustomerName + "\n" +
"Address : " + cust.CustomerAddress + "\n" +
"Balance :$ " + cust.ViewBalance);
}
}
return string.Format("{0}", "Customer does not exists!");
}
public string ViewBalance(int act)
{
foreach (Customer cust in custList)
{
if (cust.AccountNumber == act)
{
return string.Format("Balance : $" + cust.ViewBalance);
}
}
return string.Format("{0}", "Customer does not exists!");
}
}
Each customer has their own account number that is already assigned.
How are you consuming this service ?
I mean to say how you are creating your client (can you post some code).
Following salient points are taken into account while consuming the service
Adding a service reference
Creating an instance of the client
Calling the web methods of the instance

Get variables for ipn option_name_1_1 C#

I have a paypal shopping cart button that has 3 option dropdowns. The first is Style - Tee, Sweat, Hood - this one has a price tied to each, then there are two others Size and Color. This is a C# ASP.NET app. If I look at the whole response that the listener gets ( all the variables) the style is the 'option_name1_1' and it returns "Style" as it should. But in the list 'option_selection_1_1' = "Sweat", which is what I selected, but it doesn't show anything when I call that value. This is the code that puts the response to the user.
if (strResponse.StartsWith("SUCCESS"))
{
PDTHolder pdt = PDTHolder.Parse(strResponse);
Label1.Text =
string.Format("" + pdt.PayerFirstName + " " + pdt.PayerLastName + " for your payment of " + pdt.GrossTotal + " " + pdt.Currency + " option:"+pdt.OptionName+" : "+pdt.OptionOne+":"+pdt.OptionName2+ " :" + pdt.OptionTwo+"!",
pdt.PayerFirstName, pdt.PayerLastName,
pdt.PayerEmail, pdt.GrossTotal, pdt.Currency);
This is the class the the listener uses to parse the response.
public class PDTHolder
{
public PDTHolder()
{
}
private double grosstotal;
public double GrossTotal
{
get { return grosstotal; }
set { grosstotal = value; }
}
private int invoicenumber;
public int InvoiceNumber
{
get { return invoicenumber; }
set { invoicenumber = value; }
}
private string paymentstatus;
public string PaymentStatus
{
get {return paymentstatus; }
set { paymentstatus = value; }
}
private string payerfirstname;
public string PayerFirstName {
get { return payerfirstname; }
set { payerfirstname = value; }
}
private double paymentfee;
public double PaymentFee {
get { return paymentfee; }
set { paymentfee = value; }
}
private string businessemail;
public string BusinessEmail {
get { return businessemail; }
set { businessemail = value; }
}
private string payeremail;
public string PayerEmail {
get { return payeremail; }
set { payeremail = value; }
}
private string txtoken;
public string TxToken {
get { return txtoken; }
set { txtoken = value; }
}
private string payerlastname;
public string PayerLastName {
get { return payerlastname; }
set { payerlastname = value; }
}
private string receiveremail;
public string ReceiverEmail {
get { return receiveremail; }
set { receiveremail = value; }
}
private string itemname;
public string ItemName {
get { return itemname; }
set { itemname = value; }
}
private string currency;
public string Currency {
get { return currency; }
set {currency = value; }
}
private string transactionid;
public string TransactionId {
get { return transactionid; }
set { transactionid = value; }
}
private string subscriberid;
public string SubscriberId {
get { return subscriberid; }
set { subscriberid = value; }
}
private string custom;
public string Custom {
get { return custom; }
set { custom = value; }
}
private string optionone;
public string OptionOne{
get{ return optionone;}
set{optionone = value;}
}
private string optionname;
public string OptionName
{
get { return optionname; }
set { optionname = value; }
}
private string optiontwo;
public string OptionTwo{
get{ return optiontwo;}
set{optiontwo = value;}
}
private string optionname2;
public string OptionName2
{
get { return optionname2; }
set { optionname2 = value; }
}
private double price;
public static PDTHolder Parse(string postData)
{
String sKey, sValue;
PDTHolder ph = new PDTHolder();
try
{
//split response into string array using whitespace delimeter
String[] StringArray = postData.Split('\n');
// NOTE:
/*
* loop is set to start at 1 rather than 0 because first
string in array will be single word SUCCESS or FAIL
Only used to verify post data
*/
// use split to split array we already have using "=" as delimiter
int i;
for (i = 1; i < StringArray.Length - 1; i++)
{
String[] StringArray1 = StringArray[i].Split('=');
sKey = StringArray1[0];
sValue = HttpUtility.UrlDecode(StringArray1[1]);
// set string vars to hold variable names using a switch
switch (sKey)
{
case "mc_gross":
ph.GrossTotal = Convert.ToDouble(sValue);
break;
case "invoice":
ph.InvoiceNumber = Convert.ToInt32(sValue);
break;
case "payment_status":
ph.PaymentStatus = Convert.ToString(sValue);
break;
case "first_name":
ph.PayerFirstName = Convert.ToString(sValue);
break;
case "mc_fee":
ph.PaymentFee = Convert.ToDouble(sValue);
break;
case "business":
ph.BusinessEmail = Convert.ToString(sValue);
break;
case "payer_email":
ph.PayerEmail = Convert.ToString(sValue);
break;
case "Tx Token":
ph.TxToken = Convert.ToString(sValue);
break;
case "last_name":
ph.PayerLastName = Convert.ToString(sValue);
break;
case "receiver_email":
ph.ReceiverEmail = Convert.ToString(sValue);
break;
case "item_name":
ph.ItemName = Convert.ToString(sValue);
break;
case "mc_currency":
ph.Currency = Convert.ToString(sValue);
break;
case "txn_id":
ph.TransactionId = Convert.ToString(sValue);
break;
case "custom":
ph.Custom = Convert.ToString(sValue);
break;
case "subscr_id":
ph.SubscriberId = Convert.ToString(sValue);
break;
case "option_selection1_1":
ph.OptionOne = Convert.ToString(sValue);
break;
case "option_name1_1":
ph.OptionName = Convert.ToString(sValue);
break;
case "option_selection1_2":
ph.OptionTwo = Convert.ToString(sValue);
break;
case "option_name1_2":
ph.OptionName2 = Convert.ToString(sValue);
break;
}
}
return ph;
}
catch (Exception ex)
{
throw ex;
}
}
}
Here is a snipet from my IPN: I hope it helps:
for (var iloop = 1; iloop <= Convert.ToInt32(inTransaction["num_cart_items"]); iloop++)
{
var currentitem = new PurchasedItem(ID, inTransaction["item_name" + iloop],
inTransaction["mc_gross_" + iloop], inTransaction["tax" + iloop],
inTransaction["quantity" + iloop], inTransaction["item_number" + iloop],
inTransaction["mc_shipping" + iloop], inTransaction["mc_handling" + iloop],
new Dictionary<string, string>());
foreach (var argument in inTransaction)
{
var match = Regex.Match(argument.ToString(), #"option_name(\d)_" + iloop);
if (!match.Success) continue;
var buildselection = "option_selection" + match.Groups[1].Value + "_" + iloop;
var key = inTransaction[argument.ToString()];
var value = inTransaction[buildselection];
currentitem.AddAdditionalInfo(new KeyValuePair<string, string>(key, value));
}
PurchasedItem.Add(currentitem);
}
WireAllComponents();

Displaying all items in another class

My problem is that I have a List<> variable connected to another class, and I want to get all the items from that List<> and put it into a string.
In the result string, i'd like to see callNum, copyNum, content, author, year, title
Here is where I'm trying to put it into a string
public class CItemControl
{
//declare a list variable
private List<CItem> mItems;
private CItem mNewItem;
//a method that instantiates the list
public CItemControl()
{
mItems = new List<CItem>();
}
//attribute to get all items
public List<CItem> Items
{
get { return mItems; }
}
public CItem NewItem
{
get { return mNewItem; }
}
//method to add item to the CItem list
public void AddItem(int callNum, int copyNum, string content, string author, string year)
{
mNewItem = new CItem(callNum, copyNum, content, author, year);
mItems.Add(mNewItem);
}
//method to return all items to a string
public CItem ListAllItems()
{
string allItems;
}
Here is the class where I'm trying to get the items from. There will be variables added later.
class CItem
{
//declare attributes
private string mTitle;
private string mAuthor;
private string mContent;
private string mYear;
private int mCopyNum;
private int mCallNum;
private bool mHold = false;
private bool mBorrowed = false;
private bool mShelf = false;
//overload a constructor
public CItem(int CallNum, int CopyNum, string Content, string Author, string Year)
{
callNum = CallNum;
copyNum = CopyNum;
content = Content;
author = Author;
year = Year;
}
//create the default constructor
public CItem()
{
callNum = 0;
copyNum = 0;
content = "";
author = "";
year = "";
}
//set attributes
public int callNum
{
get { return mCallNum; }
set { mCallNum = value; }
}
public string content
{
get { return mContent; }
set { mContent = value; }
}
public string author
{
get { return mAuthor; }
set { mAuthor = value; }
}
public string year
{
get { return mYear; }
set { mYear = value; }
}
public string title
{
get { return mTitle; }
set { mTitle = value; }
}
public int copyNum
{
get { return mCopyNum; }
set { mCopyNum = value; }
}
public bool hold
{
get { return mHold; }
}
public bool borrowed
{
get { return mBorrowed; }
}
public bool shelf
{
get { return mShelf; }
}
//display information for users
public string displayInfo()
{
return "Call Number: " + callNum + ". Copy Number: " + copyNum + ". Title: " + title +
". Author: " + author + ". Year Published: " + year + ". Content: " + content;
}
//new method to display status of item
public string displayStatus()
{
if (borrowed == true)
return "Item is currently being borrowed.";
if (shelf == true && hold == false)
return "Item is available for borrowing.";
else
return "Item is on hold";
}
Any help is much appreciated!
Thanks in advance.
ListAllItems shall look something like this
public string ListAllItems()
{
var sb = new StringBuilder(); // var is of type StringBuilder
mItems.ForEach(item => sb.Append(item.displayInfo());
return sb.ToString();
}
return String.Join("; ", allItems.Select(item => item.displayInfo()));
You don't provide a lot of informations on how and what informations you want in your result string.
Can't you achieve this objective with a simple loop ?
using System.Text;
(...)
public string ListAllItems()
{
StringBuilder allItems = new StringBuilder();
foreach(CItem itm in Items){
allItems.AppendLine(itm.displayInfo());
}
return allItems.ToString();
}
Stringbuilder is optional but is faster than string concatenation.
I don't normally like to add formatter methods to property bags like this. If you want the flexibility to change have many formatting implementations, you might want to make a seperate class do the formatting.
public interface IFormatter<in T>
{
string Format(T obj);
}
public class CItemFormatter : IFormatter<CItem>
{
public string Format(CItem item)
{
//formatting logic
}
}

Categories