I wonder if there's any way to match the names in a list with the elements in a class:
I have a class:
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
and a List: List<exampleClass> EnfSist
So that's the way the list is made. Now I would like to know how to match or identify the string inside "name" from my list. To match this class:
tbl_sistematicas b = new tbl_sistematicas
{
ap_enf_id_enfermedad = Convert.ToInt32(EnfSist[0].value),
ap_pac_inicio = Convert.ToInt32(EnfSist[1].value),
ap_pac_inicio_periodo = Convert.ToInt32(2].value),
ap_pac_duracion = Convert.ToInt32(EnfSist[3].value),
ap_pac_duracion_periodo = Convert.ToInt32(EnfSist[4].value),
ap_pac_tratamiento = EnfSist[5].value
};
Once being able to match the same names I won't have to specify each index of every element in the list. The elements in the list have the same name as in the table. Not all elements of the class are being used.
I have something like this: tbl_sistematicas bh = EnfSist.FindAll(x => x.name == bh.?????? );
If I understand the question, you can do this using something like automapper or ValueInjector
An example using ValueInjector
void Main()
{
List<exampleClass> EnfSist = new List<exampleClass>();
EnfSist.Add(new exampleClass { name = "ap_enf_id_enfermedad", value = "12" });
EnfSist.Add(new exampleClass { name = "apap_pac_inicio" , value = "34" });
// etc
tbl_sistematicas b = new tbl_sistematicas();
b.InjectFrom<MyInjection>(EnfSist);
}
public class MyInjection : KnownSourceValueInjection<List<exampleClass>>
{
protected override void Inject(List<exampleClass> source, object target)
{
foreach(var entry in source)
{
var property = target.GetProps().GetByName(entry.name, true);
if (property != null)
property.SetValue(target, Convert.ChangeType(entry.value, property.PropertyType));
}
}
}
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
public class tbl_sistematicas
{
public int ap_enf_id_enfermedad { get; set; }
public int apap_pac_inicio { get; set; }
public int ap_pac_inicio_periodo { get; set; }
public int ap_pac_duracion { get; set; }
public int ap_pac_duracion_periodo { get; set; }
public string ap_pac_tratamiento { get; set; }
}
Note, this will throw an exception if the value can not be converted to an int
Related
I have got an object like below
public class MainObj
{
public int BankDetailPercentage { get; set; }
public int PersonalDetailPercentage { get; set; }
public BankDetail BankDetail { get; set; }
public PersonalDetail PersonalDetail { get; set; }
}
public class BankDetail
{
public string Name { get; set; }
public string Branch { get; set; }
public string AccountNumber { get; set; }
}
public class PersonalDetail
{
public string Name { get; set; }
public string address { get; set; }
}
I need to loop through that MainObj Object and find how many properties of BankDetail and PersonalDetail objects are filled and on the basis of that I should set the percentage of filled properties in MainObj object's BankDetailPercentage and PersonalDetailPercentage fields and return it. How can I accomplish this, I have tried below but couldn't get how to do it
public MainObject calculatePercentage(MainObject mainObject)
{
int bdCount = 0, pdCount = 0, bdTotal = 3, pdTotal = 2;
PropertyInfo[] properties = typeof(MainObject).GetProperties();
foreach (var property in properties)
{
var value = property.GetValue(mainObject);
if (property.Name == "BankDetail")
{
//
}
}
return mainObject;
}
First you will need to get the instance of the object in question (which you have done in your code above.
var value = property.GetValue(mainObject);
Then you need to count how many properties are contained in that object. To do that we need to first get the properties.
var subProperties = property.PropertyType.GetProperties();
var propertyCount = subProperties.Length;
Now we need to check each of those properties to see if a value is set.
var populatedCount = 0;
foreach (var subProperty in subProperties)
{
if (!string.IsNullOrEmpty(subProperty.GetValue(value)))
{
populatedCount++;
}
}
Then take the percentage.
var percentage = (float)populatedCount / propertyCount;
I have these:
public class FamilyHead
{
public Guid HeadId { get; set; }
public string Name { get; set; }
}
public class Citizen
{
public Guid Id { get; set; }
public string Name { get; set; }
public short Age { get; set; }
// more properties
[ForeignKey("FamilyHead")]
public Guid HeadId { get; set; }
public virtual FamilyHead FamilyHead { get; set; }
}
public class CitizenDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
public short Age { get; set; }
public Guid HeadId
public string HeadName { get; set; }
}
I can manually map it via extension method if it is a single instance:
public static CitizenDTO ToDTO(this Citizen citizen)
{
if (citizen == null) return null;
return new CitizenDTO {
Id = citizen.Id,
Name = citizen.Name,
HeadId = citizen.HeadId,
HeadName = citizen.FamilyHead.Name
}
}
var dto = aCitizen.ToDTO();
But how to map a list of citizens? I think Select() might do the work but I only know how to do it if the model and the dto have a same structure. Like this example:
IEnumerable<int> integers = new List<int>() { 1, 2, 3, 4, 5 };
IEnumerable<string> strings = integers.Select(i => i.ToString());
So how to map a list of it?
You can use Linq Select() as you used for string in your question, no need to write long extension method
IEnumerable<CitizenDTO> dto = citizens.Select(x => x.ToDTO());
I found the answer before finishing my question. Just iterate through the list and add mapped DTO to it. Silly me
// Extension method
public static IEnumerable<CitizenDTO> ToDTO(this IEnumerable<Citizen> citizens)
{
if (citizen == null) return null;
var dto = new List<CitizenDTO>();
foreach(var citizen in citizens) {
dto.Add(citizen.ToDTO());
}
return dto;
}
// How to use
IEnumerable<CitizenDTO> result = listOfCitizens.ToDTO();
I have a situation where I have a generic method which accepts an object of type generic and I want to write a LINQ query on that object.
Here is an example:
Generic Method:
public static void GetNonNonVerifiedPersons<TResult>(Person<TResult> model)
{
// How To Write LINQ Here to get non verified person
}
Student Class:
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsVerified { get; set; }
}
Teacher Class:
public class Teacher
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsVerified { get; set; }
}
Person Class:
public class Person<T>
{
public List<T> PersonList { get; set; }
}
Main Class:
// 1. Get Non Verified Students
var persons = new Person<Student>();
var students = new List<Student>()
{
new Student { Id = 1, Name = "Student_A", IsVerified = true },
new Student { Id = 2, Name = "Student_B", IsVerified = false },
};
persons.PersonList = new List<Student>();
persons.PersonList.AddRange(students);
GetNonNonVerifiedPersons(persons);
// 2. Get Non Verified Teachers
var persons2 = new Person<Teacher>();
var teachers = new List<Teacher>()
{
new Teacher { Id = 1, Name = "Teacher_A", IsVerified = true },
new Teacher { Id = 2, Name = "Teacher_B", IsVerified = false },
new Teacher { Id = 3, Name = "Teacher_C", IsVerified = false },
};
persons2.PersonList = new List<Teacher>();
persons2.PersonList.AddRange(teachers);
GetNonNonVerifiedPersons(persons2);
You should use interface to be able to specify the type of Teacher and Student in generic type. When you use where clause compiler is able to do the type checks at compile time.
public interface IHuman
{
string Name { get; set; }
bool IsVerified { get; set; }
}
public class Teacher : IHuman
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsVerified { get; set; }
}
public class Student : IHuman
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsVerified { get; set; }
}
And then your method should be like this. Here we have where clause that says only accept generic type TResult when implements IHuman.
public static IEnumerable<TResult> GetNonNonVerifiedPersons<TResult>(Person<TResult> model) where TResult : IHuman
{
return model.PersonList.Where(x => !x.IsVerified);
}
Update : I highly suggest you to make the big changes because its how it should be.
Other way which is not common and extremely slow is to check for the types at runtime.
public static IEnumerable<TResult> GetNonNonVerifiedPersons<TResult>(Person<TResult> model)
{
var list = model.PersonList;
var t = list.FirstOrDefault() as Teacher;
if (t != null)
{
return model.PersonList.Where(x => !(x as Teacher).IsVerified);
}
var s = list.FirstOrDefault() as Student;
if (s != null)
{
return model.PersonList.Where(x => !(s as Student).IsVerified);
}
return null;
}
May be this can do the trick:
IList<Person<TResult>> xyz = new List<Person<TResult>>();
var list = xyz.Where(a => a.GetType() == typeof(Student).IsVerified);
I didn't check it in IDE but something like this would work
I have developed my first API controlled in MVC4 and through the scaffolding I have got it to automatically output a list of items:
// GET api/ItemList
public IEnumerable<ItemOption> GetItemOptions()
{
var itemoptions = db.ItemOptions.Include(i => i.Item);
return itemoptions.AsEnumerable();
}
This shows all the item properties from my model:
public class ItemOption
{
public int ItemOptionId { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
public string test1 { get; set; }
public double PriceNet { get; set; }
}
How can I specify specific fields I wish to be returned? For example, I just want the ItemOptionId, Active and Name to be returned.
I have tried adding additional includes, but this seems to be at an object level.
Try creating a new type to represent the properties you'd like to return:
public class ItemOptionResult
{
public int ItemOptionId { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
}
And then projecting your ItemOption collection, like this:
// GET api/ItemList
public IEnumerable<ItemOptionResult> GetItemOptions()
{`enter code here`
var itemoptions =
db.ItemOptions
.Select(i =>
new ItemOptionResult
{
ItemOptionId = i.ItemOptionId,
Active = i.Active,
Name = i.Name
});
return itemoptions.AsEnumerable();
}
Try this :
var itemoptions = db.ItemOptions.Select(io => new ItemOption()
{
ItemOptionId = io.ItemOptionId,
Active = io.Active ,
Name = io.Name
}
return itemoptions.AsEnumerable();
So I want to create a MVC helper where users can pass in a collection of expressions and the collection to pull those values from. This will create a table with the column Names and then a list of the values for those columns.
public class ColumnDefinition<T> where T: class
{
public Expression<Func<T,object>> Property { get; set; }
public string DisplayName { get; set; }
public string DefaultValue { get; set; }
public bool IsVisisble { get; set; }
public string CssClass { get; set; }
}
So the helper might look like this:
public static IHtmlString ToTable<T>(this HtmlHelper helper, IEnumerable<T> list, IEnumberable<ColumnDefinition<T>> columnDefs) where T: class
{
....
}
I know how to get the Property name fromthe Expression<Func<T,object>>, but not sure how to wrtiethe select statement for the list. this should work to get the values:
var someList= list.Select(() => columnDefs.Select(c => c.Property)).ToList();
I am trying to figure out how to Line up the Name with the value. So an exmaple might be this:
var colDef = new List<ColumnDefinition<Foo>>()
{
new ColumnDefinition<Foo>()
{
Property = f => f.Id,
DisplayName = "Foo"
},
new ColumnDefinition<Foo>()
{
Property = f => f.Bar.Name,
}
}
So when that set of column definitions gets passed into the helper, I'd like to Get all the property names unless the DisplayName is present (i understand how to get the names) then I want to write the data for each one of those column definitions.
Update
So I have this so far:
public static class DataTablesHelper
{
public static DataTableModel GnerateColumns<T>(IEnumerable<T> list,
IEnumerable<ColumnDefinition<T>> columnDefinitions) where T: class
{
foreach (var o in list)
{
var newList = GetInfo(o, columnDefinitions.ToList());
}
return new DataTableModel();
}
private static List<string> GetInfo<T>(T source, IEnumerable<ColumnDefinition<T>> columnDefinitions) where T : class
{
return columnDefinitions.Select(columnDefinition => columnDefinition.Property(source).ToString()).ToList();
}
}
public class ColumnDefinition<T> where T: class
{
public Func<T,object> Property { get; set; }
public string DisplayName { get; set; }
public string Value { get; set; }
public string SortValue { get; set; }
public bool IsVisisble { get; set; }
public string CssClass { get; set; }
}
This seems to work on getting the values and I can grab the Property names later. Ideally, it would be nice to pass in a string formatter to format the output.
Update 2
So, using this technique which has been part of my core library now for some time, I came up with this to allow for simple formatting:
private static List<string> GetInfo<T>(T source, IEnumerable<ColumnDefinition<T>> columnDefinitions) where T : class
{
var listValues = new List<string>();
foreach (var columnDefinition in columnDefinitions.ToList())
{
var prop = columnDefinition.Property(source);
var definition = columnDefinition;
TypeSwitch.Do(prop, TypeSwitch.Case<DateTime>(p => listValues.Add(p.ToString(definition.Format))),
TypeSwitch.Default(() => listValues.Add(prop.ToString())));
}
return listValues;
}
I added a string that will house the formatter.
public class ColumnDefinition<T> where T: class
{
public Func<T,object> Property { get; set; }
public string Format { get; set; }
public string DisplayName { get; set; }
public string Value { get; set; }
public string SortValue { get; set; }
public bool IsVisisble { get; set; }
public string CssClass { get; set; }
}