Here I came up with the first approach: that is, using foreach clause on DataSet to get the items and fill in your Entity. But this method can't be reused when the something changes.
So I think maybe reflection should be the best approach for my scenario. below are the details:
1.My entity is defined below:
using System.ComponentModel;
namespace WarningServiceForYM.Model
{
public class StuffEntity
{
[Description("企业ID")]
public string EnterpriseID { get; set; }
[Description("冰柜编号")]
public string FridgeID { get; set; }
[Description("冰柜名称")]
public string FridgeName { get; set; }
[Description("手机号码")]
public string PhoneNumber { get; set; }
[Description("设备名称")]
public string EquipmentName { get; set; }
[Description("采集参数")]
public string PickingParams { get; set; }
[Description("一路温度")]
public string TempOne { get; set; }
[Description("二路温度")]
public string TempTwo { get; set; }
[Description("三路温度")]
public string TempThree { get; set; }
[Description("四路温度")]
public string TempFour { get; set; }
[Description("五路温度")]
public string TempFive { get; set; }
[Description("六路温度")]
public string TempSix { get; set; }
[Description("七路温度")]
public string TempSeven { get; set; }
[Description("八路温度")]
public string TempEight { get; set; }
[Description("温度最低")]
public string Min { get; set; }
[Description("温度最高")]
public string Max { get; set; }
[Description("采集时间")]
public string PickingTime { get; set; }
[Description("通知间隔")]
public string WarningPeriod { get; set; }
[Description("延时")]
public string PendingTime { get; set; }
[Description("通知开关")]
public string Switch { get; set; }
[Description("最后通知时间")]
public string LastInformTime { get; set; }
}
}
Below is the DataSet screenshot:
I have saved this DataSet's data into csv file, pls click here to find it.
the inner properties in the StuffEntity have the same Description as the column headers in DataSet.
Would any one give me a method to show how to convert this Dataset to StuffEntity ? thx.
Ok, using reflection:
public static T GetEntity<T>(DataRow row) where T : new()
{
var entity = new T();
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
//Get the description attribute
var descriptionAttribute = (DescriptionAttribute)property.GetCustomAttributes(typeof(DescriptionAttribute), true).SingleOrDefault();
if (descriptionAttribute == null)
continue;
property.SetValue(entity, row[descriptionAttribute.Description]);
}
return entity;
}
You can use it like:
foreach (DataRow dataRow in dataSet.Tables[0].Rows)
{
var e = GetEntity<StuffEntity>(dataRow);
Console.WriteLine(e.EnterpriseID);
}
It's a generic implementation, so you can use it with any other types or datasets you want.
I took care to made it as simple as possible, so it can be widely improved adding some consistences, like checking if the column name exists before setting the entity value or verifying duplicate descriptions as needed. It can also be converted to an extension method for the DataRow, DataTable or DataSet, for example.
I my case Your code almost worked, but
descriptionAttribute is always null so it continues to the point where I get no results back
var descriptionAttribute = (DescriptionAttribute)property.GetCustomAttributes(typeof(DescriptionAttribute), true).SingleOrDefault();
if (descriptionAttribute == null)
continue;
I am not sure what is happening to the variable descriptionAttribute and it is null all the time.
So I changed #natenho code like this and it worked for me.
public static T GetEntity<T>(DataRow row) where T : new()
{
var entity = new T();
var properties = typeof(T).GetProperties();
foreach (var property in properties)
{
//Get the description attribute
//var descriptionAttribute = (DescriptionAttribute)property.GetCustomAttributes(typeof(DescriptionAttribute), true).SingleOrDefault();
//if (descriptionAttribute == null)
// continue;
if (row[property.Name].ToString() != "")
{
property.SetValue(entity, row[property.Name]);
}
}
return entity;
}
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 need to compare between my object and a list.
List contains attribute "nom_colonne", it fill by a query and the result is a list of attributes (same like my object AppareilsReparations)
For example :
if droit_utilisateur.nom_colonne = "Num_dossier"
so i keep the value in arp.num_dossier
But if i don't have this value of my list droit_utilisateur :
arp.num_dossier will be null.
I wanted to cast my object with System.Collections.IList but impossible to cast. I have an error.
public class AppareilsReparations
{
public string Num_dossier { get; set; }
//public string reference_aff { get; set; }
public int Id { get; set; }
public Guid Uid { get; set; }
public string ref_sav { get; set; }
public CodeDefaut codedefaut { get; set; }
public CodeSymptome codesymptome { get; set; }
}
public class Droits
{
public int id { get; set; }
public int utilisateur_id { get; set; }
public string nom_table { get; set; }
public string nom_colonne { get; set; }
}
AppareilsReparations arp = db.Query<AppareilsReparations>
("select * from v_appareils_reparations where ref_sav_client =#ref_sav", new { ref_sav }).SingleOrDefault();
List<Droits> droit_utilisateur = GetDroits("admin");
//var appareil = new List<AppareilsReparations>();
IList appareil = (IList)arp;
var result = droit_utilisateur.Where(x => !appareil.Contains(x.nom_colonne)).ToList();
That's cause AppareilsReparations is not a type of IList and thus your cast would always fail IList appareil = (IList)arp;. Probably you wanted to do like below; just comparing with Num_dossier field of AppareilsReparations type
var result = droit_utilisateur.Where(x => x.nom_colonne == arp.Num_dossier).ToList();
i have found my problem, i post my code for everybody :
List<Droits> droit_utilisateur = GetDroits(username);
Type myType = e.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());
foreach (PropertyInfo prop in e.GetType().GetProperties())
{
object propValue = prop.Name;
if (droit_utilisateur.Any(s => s.nom_colonne.Contains(prop.Name/*, StringComparison.OrdinalIgnoreCase)*/) == false))
{
prop.SetValue(e, Convert.ChangeType(null, prop.PropertyType), null);
}
}
return e;
I am using Linq to Entity , Linq query returning a ToList() and storing multiple rows in DataSourcesModel class. Later i am using foreach to iterate items and store values in DataSourcesModelDTO, till here working fine.
Now question is DataSourcesModelDTO dto storing only one row value.
I am expecting it should store multiple row value. How to achieve this in extension method?
** var datasoruceModeltDTO = DataSourcesDTOTransformers.ToDTO(result);**
public static class DataSourcesDTOTransformers
{
public static DataSourcesModelDTO ToDTO(this List<DataSourcesModel> model)
{
if (model == null) { return null; }
var dto = new DataSourcesModelDTO();
ToDTO(model, dto);
return dto;
}
public static void ToDTO(List<DataSourcesModel> model1, DataSourcesModelDTO dto)
{
foreach (var model in model1)
{
dto.DataSourceConfigID = model.DataSourceConfigID.ToString();
dto.DataSourceID = model.DataSourceID.ToString();
dto.Name = model.Name;
dto.server = model.server;
dto.LastModified = model.LastModified;
dto.Instance = model.Instance;
}
}
}
[DataContract]
public class DataSourcesModelDTO
{
[DataMember]
public string DataSourceID { get; set; }
[DataMember]
public string DataSourceConfigID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string server { get; set; }
[DataMember]
public string Instance { get; set; }
[DataMember]
public bool Deleted { get; set; }
[DataMember]
public DateTime LastModified { get; set; }
[DataMember]
public DateTime LastSync { get; set; }
}
foreach (var model in model1)
{
dto.DataSourceConfigID = model.DataSourceConfigID.ToString();
You are setting the properties of the same dto object every time in the loop. I would rearrange your toDTO methiod to either:
take in a single DataSourcesModel object and return a single DataSourcesModelDTO object (calling the method from within a loop or Linq query), or
take in an IEnumerable<DataSourcesModel> and return an IEnumerable<DataSourcesModelDTO>
How to achieve this in extension method?
Not sure why you need an extension method, but the appropriate signature would be:
public static IEnumerable<DataSourcesModelDTO> ToDTOCollection (this IEnumerable<DataSourcesModel> model)
I'll let you work out what the implementation would be. Hint: You could create a List<DataSourcesModelDTO> within the method and populate it with new objects the same way you are now.
First of all , I'm new to reflection . I've created class :
using System.Reflection;
public class EmployeeInfo
{
public string EmployeeName { get; set; }
public string PhoneNumber { get; set; }
public string Office { get; set; }
public string Department { get; set; }
public string Position { get; set; }
public string PhoneType { get; set; }
public bool IsPublic { get; set; }
}
Now I'm trying to develop a method that will populate all the properties using some business logic (if null then empty string etc) via reflection, and returning a list of EmployeeInfo. I thought it should look something like this :
public List<Models.EmployeeInfo> GetEmployeeInfo(SPListItemCollection splic)
{
var listEmployeeInfo = new List<Models.EmployeeInfo>();
var propertyNames = new List<string>() {"EmployeeName","Position","Office","IsPublic"};
foreach (SPListItem item in splic)
{
var employeeInfo = new Models.EmployeeInfo();
foreach (var propertyName in propertyNames)
{
string newData = "";
if (item[propertyName] != null)
{
newData = item[propertyName].ToString();
}
employeeInfo.GetProperty(propertyName).SetValue(employeeInfo, newData, null);
}
listEmployeeInfo.Add(employeeInfo);
}
return listEmployeeInfo;
}
But I can't call GetProperty or SetValue extension methods at this line :
employeeInfo.GetProperty(propertyName).SetValue(employeeInfo, newData, null);
Error Message says that my Models.EmployeeInfo class doesn't contain definition for GetProperty and no extension method GetProperty .
What is missing ?
Thank you .
GetProperty is a method on the Type class.
employeeInfo.GetType().GetProperty(propertyName).SetValue(employeeInfo, newData, null);
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; }
}