Adding values using LINQ to an object property with a Dictionary property - c#

I have a dataset which returns a couple of contact information in string(Phone, mobile, skype). I created an object with a Dictionary property where i can put the contact information in a key value pair. The problem is, I am assigning the values of the object using Linq. Hope somebody can help. Here is my code:
public class Student
{
public Student()
{
MotherContacts = new ContactDetail();
FatherContacts = new ContactDetail();
}
public ContactDetail MotherContacts { get; set; }
public ContactDetail FatherContacts { get; set; }
}
public class ContactDetail
{
public ContactDetail()
{
Items = new Dictionary<ContactDetailType, string>();
}
public IDictionary<ContactDetailType, string> Items { get; set; }
public void Add(ContactDetailType type, string value)
{
if(!string.IsNullOrEmpty(value))
{
Items.Add(type, value);
}
}
}
public enum ContactDetailType
{
PHONE,
MOBILE
}
Here's how I assign value to the Student object:
var result = ds.Tables[0].AsEnumerable();
var insuranceCard = result.Select(row => new Student()
{
MotherContacts.Items.Add(ContactDetailType.PHONE, row.Field<string>("MotherPhone"),
MotherContacts.Items.Add(ContactDetailType.MOBILE, row.Field<string>("MotherMobile")
}).FirstOrDefault();
The compiler says that the MotherContacts is not recognized in the context. What should I do?

I think your code should look like:
var insuranceCard = result.Select(row =>
{
var s = new Student();
s.MotherContacts.Items.Add(ContactDetailType.PHONE, row.Field<string>("MotherPhone");
s.MotherContacts.Items.Add(ContactDetailType.MOBILE, row.Field<string>("MotherMobile");
return s;
}).FirstOrDefault();
You are using the object initializer syntax in a wrong way. The correct use is:
new Student{MotherContacts = value} where value must be a ContactDetail.

Related

Get subclass content from object

I have the following classes
public enum Category { foo, foo1, foo2 }
public class Event
{
public DateTime Timestamp { get; set; } = DateTime.Now;
public string GameTime { get; set; }
public string Content { get; set; }
public Person Author { get; set; }
public Category Category { get; set; }
}
and
public class MemberEvent : Event
{
public Member Person { get; set; }
}
The object is created correctly, but if I want to call "Person", this is not displayed to me. If I have a var match, I can call for example match[0].Timestamp but not match[0].Person. The Event object is stored in a List, therefore also the index. I feel I'm missing something simple.
UPDATE: The Code that create the Object
var match = SessionController.Instance.Current;
DataTable dt = dataGrid.ItemsSource as DataTable;
foreach (System.Data.DataRow item in dt.Rows)
{
var memberFoo = new MemberEvent();
memberFoo.Category = Category.Warning;
memberFoo.Time = item["Time"].ToString();
var person = new Person();
person.FirstName = item["FirstName"].ToString();
person.LastName = item["LastName"].ToString();
var passport = new Passport();
passport.Active = true;
passport.PassNumber = item["Pass"].ToString();
passport.Player = person;
memberFoo.Person = passport;
match.Match.Events.Add(memberFoo);
}
SessionController.Instance.Current = match;
Cast your instance to the expected type and test for null to guard for the unexpected:
var memberEvent = match[0] as MemberEvent;
if (memberEvent != null)
{
Console.WriteLine(memberEvent.Person)
}
You will have to cast your Event into a MemberEvent if you want to access the Person property. It is not possible to get the property from Event.
List<Event> myEvents = GetMyEvents();
var myMemberEvent = (MemberEvent)myEvent[0];
It can cause an exception if it can't convert to MemberEvent.

C# Add element to an Object List using variable as List key

Let me explain, I have a model list in which I have a little more than a thousand parameters, so I have to fill the list with some variables, the thing is that I don't want to do this:
list.Add(new Model{
name1= value,
name2= value,
.....
name1000=value
});
I have an array that contains the names of the parameters in the list, so I was wondering if is possible to use that array of the names and in a loop get the variables fill in, something like this:
list.Add(new Model{
//a loop?
array[0]= value
});
Thanks.
You can achieve this using reflection. Code below
public class ModelFactory
{
private IDictionary<string, PropertyInfo> propertiesInfo { get; set; }
public ModelFactory()
{
this.propertiesInfo = typeof(Model)
.GetProperties()
.ToDictionary(p => p.Name, p => p);
}
public Model Create(string[] propertiesToInitialize, dynamic value)
{
var model = new Model();
foreach (var propertyName in propertiesToInitialize)
{
if (this.propertiesInfo.ContainsKey(propertyName))
{
var property = this.propertiesInfo[propertyName];
property.SetValue(model, value);
}
}
return model;
}
}
Model to initialize
public class Model
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
public int MyProperty4 { get; set; }
public int MyProperty5 { get; set; }
}
Usage
public void Test()
{
var propertiesToInitialize = new string[] { "MyProperty1", "MyProperty2", "MyProperty4" };
var modelFactory = new ModelFactory();
var list = new List<Model>();
list.Add(modelFactory.Create(propertiesToInitialize, 500));
Console.WriteLine("MyProperty1 " + list[0].MyProperty1); // 500
Console.WriteLine("MyProperty2 " + list[0].MyProperty2); // 500
Console.WriteLine("MyProperty3 " + list[0].MyProperty3); // 0
Console.WriteLine("MyProperty4 " + list[0].MyProperty4); // 500
Console.WriteLine("MyProperty5 " + list[0].MyProperty5); // 0
}
However as already mentioned in comments, please reconsider your model design because model with these many properties is not optimal.

C# Initialize Class with a List<T> property

I need some help on how to initialize the below object with some sample values in the Main method to perform some action.
Since I am new to C# please guide me to where can i get this information
class MobOwner
{
public string Name { get; set; }
public List<string> Mobiles { get; set; }
}
Simply initialize it within your constrcutor:
class MobOwner
{
public string Name { get; set; }
public List<string> Mobiles { get; set; }
public MobOwner() {
this.Mobiles = new List<string>();
}
}
You can also define a constructor that direclty puts the right values into your list:
class MobOwner
{
public string Name { get; set; }
public List<string> Mobiles { get; set; }
public MobOwner(IEnumerable<string> values) {
this.Mobiles = values.ToList();
}
}
Which you can than call like new MobOwner(new[] { "Mario", "Hans", "Bernd" })
First of all, I doubt if you really want set; in the Mobiles property:
typically we add/update/remove items in the list, but not assign the list as whole
MobOwner sample = new MobOwner(...);
sample.MobOwner.Add("123");
sample.MobOwner.Add("456");
sample.MobOwner.RemoveAt(1);
sample.MobOwner[0] = "789";
sample.MobOwner = null; // we, usually, don't want such code
The implementation can be
class MobOwner {
public string Name { get; set; }
public List<string> Mobiles { get; } = new List<string>();
public MobOwner(string name, IEnumerable<string> mobiles): base() {
if (null == name)
throw new ArgumentNullException("name");
if (null == mobiles)
throw new ArgumentNullException("mobiles");
Name = name;
Mobiles.AddRange(mobiles);
}
}
you can make and instance and set the variable
var owner = new MobOwner();
owner.Mobiles = new List<string>{"first", "second"};
or like so
var owner = new MobOwner {Mobiles = new List<string> {"first", "second"}};
recommanded way is to use a contructor and make the set properties private
class MobOwner
{
public string Name { get; private set; }
public List<string> Mobiles { get; private set; }
// constructor
public MobOwner(string name, List<string> mobiles)
{
Name = name;
Mobiles = mobiles;
}
}
var mobOwner = new MobOwner()
{
Name = "name";
Mobiles = new List<string>()
{
"mob1",
"mob2",
"mob3"
};
};
This creates one MobOwner object containing a list with one item
MobOwner item = new MobOwner()
{
Name = "foo",
Mobiles = new List<string>() { "bar" }
};
Another way is to add a constructor to simplify instanciation
class MobOwner
{
public string Name { get; set; }
public List<string> Mobiles { get; set; }
public MobOwner(string Name, params string[] Mobiles)
{
this.Name = Name;
this.Mobiles = new List<string>(Mobiles);
}
}
usage:
MobOwner item2 = new MobOwner("foo", "bar", "bar");
If I'm getting your purpose correctly you want to initialize these values in the "Main" method.
Constructor is a good way to initialize your properties with default values whenever you create an instance of your class.
But if you want to initialize them in another place make an instance of your class and then you can give values to its public members. like this:
MobOwner mobOwner = new MobOwner();
mobOwner.Name = "Jimmy";
mobOwner.Mobiles = new List<string>{119, 011};
or in a more modern way you can change the syntax like this(although they are the same):
MobOwner mobOwner = new(){
Name = "Jimmy",
Mobiles = new List<string>{119, 011}
};

Set a value of ilist<T> members

I have the following classes:
public class Products
{
public int Id { get; set; }
public string ProductName { get; set; }
public int Price { get; set; }
public IList<ProductFiles> ProductFiles { get; set; }
}
public class ProductFiles
{
public int NumberOfFiles { get; set; }
public int NumberOfShops { get; set; }
}
Here I am trying to set the value of the property NumberOfFiles (member of ProductFiles):
public Products CountProductFiles(int productId)
{
DB_utilities db = new DB_utilities();
object[] spParams = new object[] { productId};
Products product = new Products();
using (var reader = db.procSelect("[Products_CountFiles]", spParams))
{
reader.Read();
{
Products _products = new Products
{
ProductName = (string)reader["ProductName"],
Price = (double)reader["Price"],
// I am trying to do something like this but this does not work:
ProductFiles.NumberOfFiles = (int)reader["NumberOfFiles"]
};
Products = _products ;
}
}
return Products;
}
How can I set the value of the prop NumberOfFiles? Or is the entire concept wrong?
As ProductFiles is a collection of ProductFiles, you need to do this
Products p = new Products();
p.ProductFiles = new List<ProductFiles>();
p.ProductFiles.Add(new ProductFiles() { NumberOfFiles = 1 }); // or some other defined value.
The collection needs to be initialized before adding objects to it.
In your example, you do not treat ProductFiles as a collection, that is why you get the error.
The point of a collection is that it can contain zero or more items. You need to put an instance in the collection. You also need to create a collection to ensure that the collection itself is not null.
new Product {
Files = new List<ProductFile>() {
new ProductFile {
FileCount = 42
}
}
}
In this example, Products::ProductFiles is a list.
Hence, in order to set the value of NumberOfFiles, do something like this:
ProductFiles[i].NumberOfFiles = //whatever you want to set it to.
But, before doing all this, do not forget to instantiate the List variable. Otherwise, it will itself be NULL.

Get values from a HashSet<T> using reflection

I need a way to get the values from a generic HashSet using reflection. Here is what I've tried (you can copy/paste this on a console app):
class Program
{
public class Order
{
public int Id { get; set; }
}
public class Person
{
public string Name { get; set; }
public ICollection<Order> Orders { get; set; }
}
static void Main(string[] args)
{
var person = new Person();
person.Name = "Test Person";
person.Orders = new HashSet<Order>();
person.Orders.Add(new Order() { Id = 1 });
person.Orders.Add(new Order() { Id = 2 });
var reflectedOrders = person.GetType().GetProperty("Orders").GetValue(person, null);
Console.WriteLine("How do I iterate the reflected orders?");
Console.ReadLine();
}
}
EDIT
It's an example, in the real application I don't know which type to convert the reflected Orders. I only know the property is an ICollection<T> (turned to HashShet by EF)
Did you tried casting reflectedOrders to IEnumerable?
IEnumerable reflectedOrders = (IEnumerable)person.GetType().GetProperty("Orders").GetValue(person, null);
It should be simple as casting:
var reflectedOrders = (HashSet<Order>) person.GetType().GetProperty("Orders").GetValue(person, null);
foreach (var order in reflectedOrders)
...
What about
var orders = persons.OfType<Person>().SelectMany(p => p.Orders);

Categories