Creating and using a custom List<T> in C# - c#

I am trying to use a customized List were I have added a few additional tools. I want to apply this list to a long list of customized classes that I have created. All of the classes have an ID number and some of the tools in the List use the ID.
Here is a portion of my code that I am trying to use. I hope this help you understand my problem.
namespace Simple_Point_of _Sales_System
{
public class MyList<T> : List<T>
{
internal int SetID()
{
return this.Max(n => n.ID) + 1;
}
internal T Find(int ID)
{
return this.Find(n => n.ID == ID);
}
internal T Add(T n)
{
Read();
Add(n);
Write();
return n;
}
internal void Remove(int ID)
{
Read();
if (this.Exists(t => t.ID == ID)) RemoveAll(t => t.ID == ID);
else MessageBox.Show(GetType().Name + " " + ID + " does not exist.", "Missing Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
Write();
}
internal void Edit(int ID, T n)
{
Read();
if (this.Exists(t => t.ID == ID)) this[FindIndex(t => t.ID == ID)] = n;
else MessageBox.Show(GetType().Name + " " + ID + " does not exist.", "Missing Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
Write();
}
internal MyList<T> Read()
{
Clear();
StreamReader sr = new StreamReader(#"../../Files/" + GetType().Name + ".txt");
while (!sr.EndOfStream)
Add(new T().Set(sr.ReadLine()));
sr.Close();
return this;
}
internal void Write()
{
StreamWriter sw = new StreamWriter(#"../../Files/" + GetType().Name + ".txt");
foreach (T n in this)
sw.WriteLine(n.ToString());
sw.Close();
}
}
public class Customer
{
public int ID;
public string FirstName;
public string LastName;
}
public class Item
{
public int ID { get; set; }
public string Category { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
public class MyClass
{
MyList<Customer> Customers = new MyList<Customer>();
MyList<Item> Items = new MyList<Item>();
}
}

I think your custom list needs to put on some constraints on the generic type to allow that. I would update your signature to something like
public class MyList<T> : List<T> where T : IIdentity { .... }
Here I used IIdentity as the interface defining ID, but it could also be a class.
To update your code I would do something like this:
public interface IIdentity
{
int ID { get; }
}
public class Customer : IIdentity
{
public int ID { get; set;}
public string FirstName;
public string LastName;
}
public class Item : IIdentity
{
public int ID { get; set; }
public string Category { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
I changed the ID in Customer to be a property instead of instance variable.

Related

Adding custom logics to Mapster's mapping, possibly with AfterMapping?

After mapping Input to Output, the returned Input must have an incrementing number in its Entries[i].Id, (i.e. Entries[0].Id = 1, Entries[1].Id = 2, Entries[2].Id = 3, ...). So I tried to put it in AfterMapping:
[Mapper]
public interface IMyMapper {
Output Map(Input userTableTemplate);
}
public class RegisterMyMapper : IRegister {
public void Register(TypeAdapterConfig config) {
config.NewConfig<Input, Output>()
.Map(output => output.OutputName, input => input.Name)
.AfterMapping(output => {
foreach (var pair in output.Entries.Select((value, index) => new {value = value, index = index})) {
pair.value.Id = pair.index + 1;
}
});
}
}
public class Output {
public string OutputName { get; set; }
public IEnumerable<Entry> Entries { get; set; }
}
public class Entry { public int Id { get; set; } }
public class Input { public string Name { get; set; } }
But when running _myMapper.Map(myInput) I'm getting a null reference exception, because the private Action<Output> Action1 member of the generated code (public partial class MyMapper : IIMyMapper) is null:
public partial class MyMapper : IMyMapper
{
private Action<Output> Action1;
public Output Map(Input p1)
{
if (p1 == null)
{
return null;
}
Output result = new Output();
result.OutputName = p1.Name;
Action1.Invoke(result);
return result;
}
}

C# add item in abstract list

For a project i am working with intherentance and an abstract class. with the help of a form i want to add items into a list, but get the following error during coding: cannot create an instance abstract type or interface 'Article'. does someone know how to fixt his?
articlemanager class:
private List<Article> items;
public ArticleManager()
{
items = new List<Article>();
}
public void addArticleEmergency(Article emergencyNews)
{
items.Add(emergencyNews);
}
abstract article class:
abstract class Article
{
public int id { get; private set; }
public string title { get; private set; }
public string text { get; private set; }
public Article(int id, string title, string text)
{
this.id = id;
this.title = title;
this.text = text;
}
public bool HasID(int id)
{
if (id == this.id)
{
return true;
}
return false;
}
public override string ToString()
{
return id + ": \r\n" + title + " \r\n " + text;
}
}
}
form:
private ArticleManager articalManagerAdd;
public Form1()
{
InitializeComponent();
this.articalManagerAdd = new ArticleManager();
}
private void btnMakeNewsArticle_Click(object sender, EventArgs e)
{
if(txtNewsNumber.Text == "" || txtNewsTitle.Text == "" || txtNewsText.Text == "" || !rbEmergency.Checked && !rbNormal.Checked )
{
lbSeeNewsItem.Items.Clear();
lbSeeNewsItem.Items.Add("Please fill in all the required information");
}
else
{
if (articalManagerAdd.GetArticle(Convert.ToInt32(txtNewsNumber.Text)) == null)
{
if (rbNormal.Checked)
{
articalManagerAdd.addArticleNormal(new Article(Convert.ToInt32(txtNewsNumber.Text), txtNewsTitle.Text, txtNewsText.Text));
MessageBox.Show("Normal news article has been added");
}
else if(rbEmergency.Checked)
{
Article emergencyNews = new NewsArticle(Convert.ToInt32(txtNewsNumber.Text), txtNewsTitle.Text, txtNewsText.Text);
MessageBox.Show("Emergency news article has been added");
}
}
else
{
lbSeeNewsItem.Items.Add("This id has already been used");
}
}
}
As the comments have mentioned, you cannot create an instance of an abstract class.
So your code new Article(Convert.ToInt32(txtNewsNumber.Text), txtNewsTitle.Text, txtNewsText.Text)) will not compile.
You can inherit from a non-abstract class so your NewsArticle class would be expected to work if you just removed the abstract modifier to your Article class.
Alternatively you could add a new sub-class of Article say NormalArticle and use that in your addArticleNormal method

cannot convert from System.Collections.Generic.List<> to System.Collections.Generic.IEnumerable<>

Error occurred when trying to add qresult. Anyone can please advise / guide how to fix / amend my code? thanks
cannot convert from System.Collections.Generic.List<> to System.Collections.Generic.IEnumerable<>
public class SystemAccessList
{
public SystemAccess SystemAccess { get; set; }
public List<SystemAccess> SystemAccessList { get; set; }
SystemDbContext db;
public void setDbContext(PALMSConfigDbContext _db)
{
db = _db;
}
public SystemAccessList GetAccessList(SystemAccessList systemAccessList)
{
var qresult = db.tbl_SystemAccessList
.GroupBy(g => g.ClassID)
.AsEnumerable().Select(c =>
{
var rr = new ResultRow { Class = c.Key };
foreach (var r in db.tbl_SystemAccessList.GroupBy(gg => gg.StudentID))
{
rr.Student[r.Key] = "N";
}
foreach (var r in c.Where(w => w.ClassID == c.Key))
{
rr.Student[r.StudentID] = "Y";
}
return rr;
}).ToList();
systemAccessList.SystemAccessList.AddRange(qresult);
return systemAccessList;
}
class ResultRow
{
public ResultRow()
{
Student = new Dictionary<string, string>();
}
public string Class { get; set; }
public IDictionary<string, string> Student { get; set; }
public string GetHeader()
{
return Student.Aggregate("Class", (current, s) => current + "|" + s.Key);
}
public string GetSolidRow()
{
return Student.Aggregate(Class, (current, s) => current + "|" + s.Value);
}
}
public class SystemAccess
{
[Key]
public int ID { get; set; }
public string ClassID { get; set; }
public string StudentID { get; set; }
}
Your qresult will be of type List<ResultRow> because of the Select you have there. A List<ResultRow> is also an IEnumerable<ResultRow> which (when I assume ResultRow is a reference type (class)) by turn is an IEnumerable<Xxx> for any Xxx that is either a base class of ResultRow, or an interface that ResultRow implements.
Your SystemAccessList is of type List<SystemAccess> whose AddRange method than requires an IEnumerable<SystemAccess>.
So all would be fine if a ResultRow were a SystemAccess (by inheritance). But it is not. So you should get a message at compile-time saying the List<ResultRow> is not an IEnumerable<SystemAccess>.

How to extract the data from Generic <T> List object

I wanna create the generic function inwhich I will just pass the class name and get the data in CSV format that is from JSON object on the bases of Generic Class Type.
But I am not able to access the class member while foreach loop.
public class Lifetouch
{
public int LifetouchID { get; set; }
public string Data { get; set; }
}
public class Lifetemp
{
public int LifetempID { get; set; }
public string Data { get; set; }
}
main()
{
getPerodicListofVitalSigns <Lifetouch>(new Lifetouch());
}
public static void getPerodicListofVitalSigns <T>( T clazz)
{
List<T> list_of_measurements_Original = JsonConvert.DeserializeObject<List<T>>(json_response);
// Got the list_of_measurements_Original count 2.
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var element in list_of_measurements_Original)
{
sb.Append(element.LifetouchID + ", ") // Not able to access the element of list LifetouchID
}
sb.Append("]");
}
I would like to create the generic function inwhich I will just pass the class name and get the data (ID's) in CSV format that is from JSON object on the bases of Generic Class Type. That all the ids will pass through webservice and update the database. Its the requirement.
I would like to create the Generic function in which I would like to pass the class name as a paramenter. So in future its easy for me to use that generic function if new class added.
Now its working fine..
public class Lifetouch
{
public int LifetouchID { get; set; }
public string Data { get; set; }
}
public class Lifetemp
{
public int LifetempID { get; set; }
public string Data { get; set; }
}
main()
{
getPerodicListofVitalSigns <Lifetouch>(new Lifetouch());
getPerodicListofVitalSigns <Lifetemp>(new Lifetemp());
}
public static void getPerodicListofVitalSigns <T>( T clazz)
{
List<T> list_of_measurements_Original = JsonConvert.DeserializeObject<List<T>>(json_response);
// Got the list_of_measurements_Original count 2.
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var element in list_of_measurements_Original)
{
if (VitalSignName == "Lifetouch")
{
var vitalSign = element as Lifetouch;
dataString = dataString + (vitalSign.LifetouchID + ",");
}
else if (VitalSignName == "Lifetemp")
{
var vitalSign = element as Lifetemp;
dataString = dataString + (vitalSign.LifetempID + ",");
}
}
sb.Append("]");
string WebserviceAddress = "192..../json/reply/UpdateSyncStatus";
JSON_POST_Sender.ClassPost(WebserviceAddress, dataString), "true")
}

Dynamic class based on string parameter

I have this:
public class Blah
{
public int id { get; set; }
public string blahh { get; set; }
}
public class Doh
{
public int id { get; set; }
public string dohh { get; set; }
public string mahh { get; set; }
}
public List<???prpClass???> Whatever(string prpClass)
where string prpClass can be "Blah" or "Doh".
I would like the List type to be class Blah or Doh based on what the string prpClass holds.
How can I achieve this?
EDIT:
public List<prpClass??> Whatever(string prpClass)
{
using (var ctx = new ApplicationDbContext())
{
if (prpClass == "Blah")
{
string queryBlah = #"SELECT ... ";
var result = ctx.Database.SqlQuery<Blah>(queryBlah).ToList();
return result;
}
if (prpClass == "Doh")
{
string queryDoh = #"SELECT ... ";
var result = ctx.Database.SqlQuery<Doh>(queryDoh).ToList();
return result;
}
return null
}
}
you have to have a common supertype:
public interface IHaveAnId
{
int id { get;set; }
}
public class Blah : IHaveAnId
{
public int id { get; set; }
public string blahh { get; set; }
}
public class Doh : IHaveAnId
{
public int id {get;set;}
public string dohh { get; set; }
public string mahh { get; set; }
}
then you can do:
public List<IHaveAnId> TheList = new List<IHaveAnId>();
and in some method:
TheList.Add(new Blah{id=1,blahh = "someValue"});
TheList.Add(new Doh{id =2, dohh = "someValue", mahh = "someotherValue"});
to iterate through the list:
foreach(IHaveAnId item in TheList)
{
Console.WriteLine("TheList contains an item with id {0}", item.id);
//item.id is allowed since you access the property of the class over the interface
}
or to iterate through all Blahs:
foreach(Blah item in TheList.OfType<Blah>())
{
Console.WriteLine("TheList contains a Blah with id {0} and blahh ='{1}'", item.id, item.blahh);
}
Edit:
the 2 methods and a int field holding the autovalue:
private int autoValue = 0;
public void AddBlah(string blahh)
{
TheList.Add(new Blah{id = autovalue++, blahh = blahh});
}
public void AddDoh(string dohh, string mahh)
{
TheList.Add(new Doh{id = autovalue++, dohh = dohh, mahh = mahh});
}
Another Edit
public List<object> Whatever(string prpClass)
{
using (var ctx = new ApplicationDbContext())
{
if (prpClass == "Blah")
{
string queryBlah = #"SELECT ... ";
var result = ctx.Database.SqlQuery<Blah>(queryBlah).ToList();
return result.Cast<object>().ToList();
}
if (prpClass == "Doh")
{
string queryDoh = #"SELECT ... ";
var result = ctx.Database.SqlQuery<Doh>(queryDoh).ToList();
return result.Cast<object>.ToList();
}
return null;
}
}
in the view you then have to decide what type it is. In asp.net MVC you can use a display template and use reflection to get a good design. But then i still don't know what technology you are using.
Yet another Edit
TestClass:
public class SomeClass
{
public string Property { get; set; }
}
Repository:
public static class Repository
{
public static List<object> Whatever(string prpClass)
{
switch (prpClass)
{
case "SomeClass":
return new List<SomeClass>()
{
new SomeClass{Property = "somestring"},
new SomeClass{Property = "someOtherString"}
}.Cast<object>().ToList();
default:
return null;
}
}
}
And a controller action in mvc:
public JsonResult Test(string className)
{
return Json(Repository.Whatever("SomeClass"),JsonRequestBehavior.AllowGet);
}
then i called it with: http://localhost:56619/Home/Test?className=SomeClass
And got the result:
[{"Property":"somestring"},{"Property":"someOtherString"}]
Is this what you are trying to do?
public class Blah
{
public int id { get; set; }
public string blahh { get; set; }
}
public class Doh
{
public int id { get; set; }
public string dohh { get; set; }
public string mahh { get; set; }
}
class Program
{
public static List<T> Whatever<T>(int count) where T: new()
{
return Enumerable.Range(0, count).Select((i) => new T()).ToList();
}
static void Main(string[] args)
{
var list=Whatever<Doh>(100);
// list containts 100 of "Doh"
}
}

Categories

Resources