C# Linq Column Name as variable - c#

I have a table where I want to make a query on variable columns.
Like:
private void query(string column, string value) {
using (var db = new myDB()) {
var s1 = (from c in db.Components
where (**column** == **value**)
select new {c.id, **column**});
}
}
lets say I want to look for a supplier then it would be like:
var s1 = (from c in db.Components
where (c.supplier == "abc")
select new {c.id, c.supplier});
is there a way to pass the column name as variable?

This example can be useful i guess.
void BindGridTypeSafe()
{
NorthwindDataContext northwind = new NorthwindDataContext();
var query = from p in northwind.Products
where p.CategoryID == 3 && p.UnitPrice > 3
orderby p.SupplierID
select p;
GridView1.DataSource = query;
GridView1.DataBind();
}
void BindGridDynamic()
{
NorthwindDataContext northwind = new NorthwindDataContext();
var query = northwind.Products
.Where("CategoryID = 3 AND UnitPrice > 3")
.OrderBy("SupplierID");
GridView1.DataSource = query;
GridView1.DataBind();
}

A nice way is to use Dynamic Linq
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Something like:
var s1 = (from c in db.Components
where(column + "=" + value)
select new {c.id, **column**});

Short answer is to add library System.Linq.Dynamic as a reference and do:
string columnName = "Supplier";
var s1 = Suppliers
.Where(String.Format("{0} == \"abc\"", columnName))
.Select(new {c.id, c.supplier};
Following is a complete working example of Dynamic Linq, where column-name is a parameter:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
public class Program
{
public static void Main()
{
var lstContacts = new List<Contact>{
new Contact{Id = 1, Active = true, Name = "Chris"},
new Contact{Id = 2, Active = true, Name = "Scott"},
new Contact{Id = 3, Active = true, Name = "Mark"},
new Contact{Id = 4, Active = false, Name = "Alan"}};
string columnName = "Active";
List<Contact> results = lstContacts.Where(String.Format("{0} == true", columnName)).ToList();
foreach (var item in results)
{
Console.WriteLine(item.Id.ToString() + " - " + item.Name.ToString());
}
}
}
public class Contact
{
public int Id
{
get;
set;
}
public bool Active
{
get;
set;
}
public string Name
{
get;
set;
}
}
You can experiment with this .net-fiddle-here

I'm resurrecting this old thread because I had to work around that issue with ASP.NET Core 2.2 today. I used the System.Linq.Dynamic.Core NuGet package to create the following extension method, which works beautifully if you need to check if multiple given string values are contained within multiple given columns.
public static IQueryable<TEntity> WhereContains<TEntity>(
this IQueryable<TEntity> query,
string field,
string value,
bool throwExceptionIfNoProperty = false,
bool throwExceptionIfNoType = false)
where TEntity : class
{
PropertyInfo propertyInfo = typeof(TEntity).GetProperty(field);
if (propertyInfo != null)
{
var typeCode = Type.GetTypeCode(propertyInfo.PropertyType);
switch (typeCode)
{
case TypeCode.String:
return query.Where(String.Format("{0}.Contains(#0)", field), value);
case TypeCode.Boolean:
var boolValue = (value != null
&& (value == "1" || value.ToLower() == "true"))
? true
: false;
return query.Where(String.Format("{0} == #0", field), boolValue);
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return query.Where(String.Format("{0}.ToString().Contains(#0)", field), value);
// todo: DateTime, float, double, decimals, and other types.
default:
if (throwExceptionIfNoType)
throw new NotSupportedException(String.Format("Type '{0}' not supported.", typeCode));
break;
}
}
else
{
if (throwExceptionIfNoProperty)
throw new NotSupportedException(String.Format("Property '{0}' not found.", propertyInfo.Name));
}
return query;
}
The code can be used with .NETStandard/.NETCore (using the aforementioned System.Linq.Dynamic.Core package) and also with ASP.NET 4.x (using the System.Linq.Dynamic package).
For further info regarding the WhereContains extension method and a full use-case info, check out this post on my blog.

Related

LINQ Filtering Select Ouput with IEnumerable<T>

I have following methods:
Controller:
...
var appmap = Services.GetReqAppMapList(value);
var applist = Services.GetApplicationList(docid, appid, reqid, appmap);
...
Model:
public static IEnumerable<AppMap> GetReqAppMapList(int aiRequestTypeId)
{
try
{
var appmap = new List<AppMap>();
using (var eties = new eRequestsEntities())
{
appmap = (from ram in eties.ReqAppMaps
where ram.IsActive == 1
select new AppMap
{
RequestTypeId = ram.RequestTypeId
}).ToList();
return appmap;
}
}
catch(Exception e)
{
throw e;
}
}
public static IEnumerable<TicketApplication> GetApplicationList(int aiDocumentTypeId, int aiApplicationTypeId, int aiRequestTypeId, IEnumerable<AppMap> appmap)
{
try
{
var applicationlist = new List<TicketApplication>();
using (var applicationentity = new eRequestsEntities())
{
applicationlist = (from app in applicationentity.Applications
where 1==1
<<<Some Conditions Here???>>>
== && appmap.Contains(app.ApplicationTypeId) ==
&& app.IsActive == 1
select new TicketApplication
{
ApplicationId = app.ApplicationId,
Description = app.Description,
DeliveryGroupId = app.DeliveryGroupId,
ApplicationTypeId = app.ApplicationTypeId,
DeliveryTypeId = app.DeliveryTypeId,
DocumentTypeId = app.DocumentTypeId,
SupportGroupId = app.SupportGroupId
}).OrderBy(a => a.Description).ToList();
return applicationlist;
}
And I was thinking how can filter query result of GetApplicationList using the result from GetReqAppMapList
I'm kinda stuck with the fact that I must convert/cast something to the correct type because every time I do a result.Contains (appmap.Contains to be exact), I always get the following error
Error 4 Instance argument: cannot convert from
'System.Collections.Generic.IEnumerable<Test.Models.AppMap>' to
'System.Linq.ParallelQuery<int?>'
You should directly join the two tables in one query.
using (var applicationentity = new eRequestsEntities())
{
applicationlist = (from app in applicationentity.Applications
join ram in applicationentity.ReqAppMaps on app.ApplicationTypeId equals ram.RequestTypeId
where ram.IsActive == 1 && app.IsActive == 1
select new TicketApplication
{
ApplicationId = app.ApplicationId,
Description = app.Description,
DeliveryGroupId = app.DeliveryGroupId,
ApplicationTypeId = app.ApplicationTypeId,
DeliveryTypeId = app.DeliveryTypeId,
DocumentTypeId = app.DocumentTypeId,
SupportGroupId = app.SupportGroupId
}).OrderBy(a => a.Description).ToList();
You can delete the other method if it is not needed anymore. No point hanging onto code which is dead.
Looks like there is no other way to do this (as far as I know), so I have to refactor the code, I hope still that there would be a straight forward conversion and matching method in the future (too lazy). Anyway, please see below for my solution. Hope this helps someone with the same problem in the future. I'm not sure about the performance, but this should work for now.
Controller:
...
var appmap = Services.GetReqAppMapList(value);
var applist = Services.GetApplicationList(docid, appid, reqid, appmap);
...
Model:
<Removed GetReqAppMapList>--bad idea
public static IEnumerable<TicketApplication> GetApplicationList(int aiDocumentTypeId, int aiApplicationTypeId, int aiRequestTypeId)
{
try
{
//This is the magic potion...
List<int?> appmap = new List<int?>();
var applist = (from ram in applicationentity.ReqAppMaps
where ram.RequestTypeId == aiRequestTypeId
&& ram.IsActive == 1
select new AppMap
{
ApplicationTypeId = ram.ApplicationTypeId
}).ToList();
foreach (var item in applist)
{
appmap.Add(item.ApplicationTypeId);
}
//magic potion end
var applicationlist = new List<TicketApplication>();
using (var applicationentity = new eRequestsEntities())
{
applicationlist = (from app in applicationentity.Applications
where 1==1
===>>>&& appmap.Contains(app.ApplicationTypeId)<<<===
&& app.IsActive == 1
select new TicketApplication
{
ApplicationId = app.ApplicationId,
Description = app.Description,
DeliveryGroupId = app.DeliveryGroupId,
ApplicationTypeId =app.ApplicationTypeId,
DeliveryTypeId = app.DeliveryTypeId,
DocumentTypeId = app.DocumentTypeId,
SupportGroupId = app.SupportGroupId
}).OrderBy(a => a.Description).ToList();
return applicationlist;
}
A side-note, C# is a strongly-typed language, just make sure your data types matches during evaluation, as int? vs int etc.., will never compile. A small dose of LINQ is enough to send some newbies circling around for hours. One of my ID-10T programming experience but just enough to remind me that my feet's still flat on the ground.

Create an Array from SQL Query Results

I have the following function that searches a database for entries where a column called "description" have the same value. Right now it just returns the first value it finds or a default value is there isn't one.
public static NewCode GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).FirstOrDefault();
}
I have this if statement to check and make sure the result isn't null, and if it is, to say that the "code isn't found"
[Authorize(parentAction: "Edit")]
public ActionResult Lookup(string Code, int? VersionId = null)
{
var Info = VisitViews.GetDescriptionByVersionId(Code, VersionId.HasValue ? VersionId.Value : 9);
var description = string.Empty;
// CHECK FOR NULL
if (Info != null)
{
description = Info.Description;
if (VersionId == 9)
{
var altInfo = VisitViews.GetAltCode(10, description);
}
if (VersionId == 10)
{
var altInfo = VisitViews.GetAltCode(9, description);
}
}
else
description = "CODE NOT FOUND";
return Json(new { Description = description });
}
My question is, instead of doing FirstOrDefault, is there a way to store the results in an array (or even to store them in a list and call ToArray on the list)? I'm trying to get all of the codes received during the sql search instead of just one so that another function I am working on can traverse the array and place the items where they need to be in a UI.
For future reference of this post, here is the answer:
Change the return type to NewCode[] and replace .FirstOrDefault() with .ToArray()
public static NewCode[] GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).ToArray();
}

method x has no supported translation to SQL when use a static class

I am using MVC platform and a jqGrid in the views. below is the part of controller code return json to the grid
IQueryable<CalendarViewModel> callendars =
from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select Matcher.Calendar(call);
if (jqGridParameters._search != false)
{
callendars = callendars.Where(jqGridParameters.WhereClause);
}
if (jqGridParameters.sidx != null)
callendars = callendars.OrderBy(
jqGridParameters.sidx.Substring(8) + " " + jqGridParameters.sord.ToLower());
var count = callendars.Count();
int pageIndex = jqGridParameters.page;
the Matcher is a static class. below is the used method of the class
public static class Matcher
{
public static CalendarViewModel Calendar(Calendar call)
{
return new CalendarViewModel
{
ID = call.ID,
Name = call.Name,
StartDate = call.StartDate,
EndDate = call.EndDate,
AcademicYear = call.AcademicYear
};
}
}
at the line
var count = callendars.Count();
i recieve this error:
Method 'KYTC.Models.CalendarViewModel Calendar(KYTC.Data.Calendar)' has no supported translation to SQL.
but when I change the LINQ query to this:
IQueryable<CalendarViewModel> callendars =
from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select new CalendarViewModel
{
ID = call.ID,
Name = call.Name,
StartDate = call.StartDate,
EndDate = call.EndDate,
AcademicYear = call.AcademicYear
};
my code is running well.
what is wrong with my class definition?
Nothing is wrong with your class definition. The problem is that you simply can't call arbitrary functions in Linq-to-SQL (or EntityFramework) queries. Only a handful of predefined methods can be translated into SQL syntax. Your final method is the correct way of returning CalendarViewModel objects from a query.
However, you could also do this:
public static Expression<Func<Calendar, CalendarViewModel>> CalendarExpression()
{
return c => new CalendarViewModel
{
ID = c.ID,
Name = c.Name,
StartDate = c.StartDate,
EndDate = c.EndDate,
AcademicYear = c.AcademicYear
};
}
var calendarExpr = Match.CalendarExpression();
IQueryable<CalendarViewModel> callendars =
(from call in (new KYTCDataContext()).Calendars
where call.AcademicYear == id
select call)
.Select(calendarExpr);

List(T) from sql db table

I want to create List(T) from sql db table
let's say i have one table
ID Name
1 xyz
2 efd
3 abc
4 pqr
i want to some code in C# who will read this db table data and write
following lines in my c# class or / notepad or whatever...
List<ItemViewModel> Items= new List<ItemViewModel>();
Items.Add(new ItemViewModel() { id= 1, name= "xyz"}
Items.Add(new ItemViewModel() { id= 2, name= "efd"}
Items.Add(new ItemViewModel() { id= 3, name= "abc"}
Items.Add(new ItemViewModel() { id= 4, name= "pqr"}
thanks in advance
Add "dapper" to your project (available on NuGet), then:
var list = connection.Query<YourType>("select * from TableName").ToList();
Or for a parameterless query:
var region = "South";
var list = connection.Query<YourType>(
"select * from TableName where Region=#region", new { region });
Here one of best code that you can got, the following method can deal with any data classes and system defined types :
public List<T> ExecuteQuery<T>(string s, SqlConnection condb, params SqlParameter[] Params)
{
List<T> res = new List<T>();
string er = "";
SqlDataReader r = null;
try {
if (condb == null)
throw new Exception("Connection is NULL");
if (string.IsNullOrEmpty(s))
throw new Exception("The query string is empty");
using (SqlCommand cm = new SqlCommand(s, condb)) {
if (Params.Length > 0) {
cm.Parameters.AddRange(Params);
}
if (cm.Connection.State != ConnectionState.Open)
cm.Connection.Open();
r = cm.ExecuteReader;
object prps = typeof(T).GetProperties;
object prpNames = prps.Select((System.Object f) => f.Name).ToList;
if (r.HasRows) {
while (r.Read) {
if (typeof(T).FullName.Contains("System.")) {
res.Add(r(0));
// Classes
} else {
object c = Activator.CreateInstance(typeof(T));
for (j = 0; j <= r.FieldCount - 1; j++) {
object jj = j;
//er = dt.Rows(jj)("ColumnName").ToLower
object fname = r.GetName(j).ToString;
er = fname;
object fType = r.GetProviderSpecificFieldType(j).ToString.ToLower;
object p = prps.Where((System.Object f) => f.Name.Trim.ToLower == fname.ToLower).ToList;
if (p.Count > 0) {
//Date or DateTime
if (fType.Contains("date")) {
if (!p(0).PropertyType.FullName.ToLower.Contains("system.nullable") && (r(fname) == null || r(fname).Equals(System.DBNull.Value))) {
p(0).SetValue(c, Now, null);
} else {
if (!(p(0).PropertyType.FullName.ToLower.Contains("system.nullable") && (r(fname) == null || r(fname).Equals(System.DBNull.Value)))) {
p(0).SetValue(c, r(fname), null);
}
}
//String
} else if (fType.Contains("string")) {
if (r(fname) == null || r(fname).Equals(System.DBNull.Value)) {
p(0).SetValue(c, "", null);
} else {
p(0).SetValue(c, r(fname), null);
}
} else {
if (!(p(0).PropertyType.FullName.ToLower.Contains("system.nullable") && (r(fname) == null || r(fname).Equals(System.DBNull.Value)))) {
p(0).SetValue(c, r(fname), null);
}
}
}
}
res.Add(c);
}
}
}
r.Close();
}
//If cm IsNot Nothing Then
// 'cm.Connection.Close()
// cm.Dispose()
//End If
} catch (Exception ex) {
if (r != null && r.IsClosed == false)
r.Close();
throw ex;
}
return res;
}
Usage :
var data = ExecuteQuery<ItemViewModel>("SELECT [ID], [Name] FROM [ItemViewTable]",
new SqlConnection("SomeConnectionString"));
If you just want a list populated with whatever data is currently in the database table, you can just do a simple query. You don't have to involve code generation.
Using linq-to-sql to read the contents of the table and create an ItemViewModel for each entry:
using(var context = new MyLinqDbContext())
{
var items = (from i in context.MyTable
select new ItemViewModel { id = ID, name = Name })
.ToList();
}
If you want C# code generated which is being created from database values and compiled into your solution, you want to use Microsofts text templating engine (T4). To get a hold of this technique, you can read up on it in detail in this blog entry.
If you understand the basics of T4, you can read up this blog, there's an example of how to dynamically create Enum classes for static lookup tables which are stored in a database. Starting from this code, you can write your own code generation template which creates the classes you need.

Flatten One-to-Many Relationship Using Dynamic LINQ

Is it possible to flatten a one-to-many relationship using dynamic LINQ?
For example, I might have a list of Users and the User class contains a list of many UserPreferences. The UserPreference class is essentially a name/value pair.
A user will define what types of user preferences are available for a group of users.
public class User
{
public string FirstName
{
get;
set;
}
public string LastName
{
get;
set;
}
public IList<UserPreference> UserPreferences
{
get;
set;
}
}
public class UserPreference
{
public UserPreference(string name, object userValue)
{
this.Name = name;
this.UserValue = userValue;
}
public string Name
{
get;
set;
}
public object UserValue
{
get;
set;
}
}
Therefore one user group might be defined in the following way:
List<User> users = new List<User>();
User user1 = new User();
user1.FirstName = "John";
user1.LastName = "Doe";
user1.UserPreferences.Add(new UserPreference("Favorite color", "Red"));
User user2 = new User();
user2.FirstName = "Jane";
user2.LastName = "Doe";
user2.UserPreferences.Add(new UserPreference("Favorite mammal", "Dolphin"));
user2.UserPreferences.Add(new UserPreference("Favorite color", "Blue"));
users.Add(user1);
users.Add(user2);
return users;
The desired output would be:
First Name Last Name Favorite Color Favorite Mammal
John Doe Red NULL
Jane Doe Blue Dolphin
Is there a way to create an anonymous type so that UserPreferences would get rolled up into the User?
For example,
var u = UserScopedSettingAttribute.Select("new (FirstName as FirstName, UserValue as FavoriteColor)", null);
string name = u.FirstName;
string color = u.FavoriteColor;
Ultimately this list of Users will get bound to an ASP.NET GridView web control. There will be a large volume of data involved in this operation and performance will be critical.
Any suggestions are appreciated!
I know it doesn't exactly answer your question, but compiling strings into new classes at runtime like dlinq does has always had kind of a bad smell to it. Consider just simply using a DataTable like this,
DataTable prefs = new DataTable();
IEnumerable<DataColumn> cols = (from u in users
from p in u.UserPreferences
select p.Name)
.Distinct()
.Select(n => new DataColumn(n));
prefs.Columns.Add("FirstName");
prefs.Columns.Add("LastName");
prefs.Columns.AddRange(cols.ToArray());
foreach (User user in users)
{
DataRow row = prefs.NewRow();
row["FirstName"] = user.FirstName;
row["LastName"] = user.LastName;
foreach (UserPreference pref in user.UserPreferences)
{
row[pref.Name] = pref.UserValue;
}
prefs.Rows.Add(row);
}
This should do it. Flattening is generally done with SelectMany extension method, but in this case I am using a let expression. The code to remove the null preferences is a bit ugly and could prob be improved but it works:
var flattenedUsers = from user in GetUsers()
let favColor = user.UserPreferences.FirstOrDefault(pref => pref.Name == "Favorite color")
let favMammal = user.UserPreferences.FirstOrDefault(pref => pref.Name == "Favorite mammal")
select new
{
user.FirstName,
user.LastName,
FavoriteColor = favColor == null ? "" : favColor.UserValue,
FavoriteMammal = favMammal == null ? "" : favMammal.UserValue,
};
My best suggestion would be to not use dynamic LINQ, but add a flatuser class and then loop through the users. The code for this is simple, and if you were able to get a linq query with similar results it would generate the same code, although you can't really tell how optimized it would be as it might involve some joins that would incur a performance penalty instead of just looping. If you were pulling this from a database using LINQ to SQL then you could use an entity relation to to get the data using linq instead of this loop.
Loop:
List<FlatUser> flatusers = new List<FlatUser>();
foreach (User u in users)
{
foreach (UserPreference up in u.UserPreferences)
{
flatusers.Add(new FlatUser
{
FirstName = u.FirstName,
LastName = u.LastName,
Name = up.Name,
UserValue = up.UserValue
});
}
}
Flat User Class:
public class FlatUser
{
public string FirstName
{
get;
set;
}
public string LastName
{
get;
set;
}
public string Name
{
get;
set;
}
public object UserValue
{
get;
set;
}
}
Unfortunately
var u = UserScopedSettingAttribute.Select("new {FirstName as FirstName, UserValue as FavoriteColor}", null);
string name = u.FirstName;
string color = u.FavoriteColor;
won't work. When you use DLINQ Select(string) the strongest compile time class information you have is Object, so u.FirstName will throw a compile error. The only way to pull the properties of the runtime generated anonymous class is to use reflection. Although, if you can wait, this will be possible with C# 4.0 like this,
dynamic u = UserScopedSettingAttribute.Select("new {FirstName as FirstName, UserValue as FavoriteColor}", null);
string name = u.FirstName;
string color = u.FavoriteColor;
I think the pragmatic answer here is to say your attempting to force C# to become a dynamic language and any solution is going to be really pushing C# to its limits. Sounds like your trying to transform a database query of columns that are only determined at query time into a collection that is based on those columns and determined at run time.
Linq and Gridview binding is really pretty and succinct and all but you have to start thinking about weighing the benefit of getting this compiler bending solution to work just so you don't have to dynamically generate gridview rows and columns by yourself.
Also if your concerned about performance I'd consider generating the raw HTML. Relying on the collection based WebForms controls to efficiently display large sets of data can get dicey.
You add in a couple of OnItemDataBound events and boxing and unboxing is going to really gum up the works. I'm assuming too your going to want to add interactive buttons and textboxes to the rows as well and doing 1000 FindControls has never been fast.
There are probably more efficient ways to do this, but to actually answer your question, I came up with the following code. (Note that I've never worked with DynamicLinq before, so there may be a better way to use it to accomplish your goal.)
I created a console application, pasted in the classes from your post, then used the following code.
static void Main(string[] args)
{
var users = GetUserGroup();
var rows = users.SelectMany(x => x.UserPreferences.Select(y => new { x.FirstName, x.LastName, y.Name, y.UserValue }));
var userProperties = rows.Select(x => x.Name).Distinct();
foreach (var property in userProperties)
{
Console.WriteLine(property);
}
Console.WriteLine();
// The hard-coded variety.
var results = users.Select(x => new
{
x.FirstName,
x.LastName,
FavoriteColor = x.UserPreferences.Where(y => y.Name == "Favorite color").Select(y => y.UserValue).FirstOrDefault(),
FavoriteAnimal = x.UserPreferences.Where(y => y.Name == "Favorite mammal").Select(y => y.UserValue).FirstOrDefault(),
});
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// The dynamic variety.
DynamicProperty[] dynamicProperties = new DynamicProperty[2 + userProperties.Count()];
dynamicProperties[0] = new DynamicProperty("FirstName", typeof(string));
dynamicProperties[1] = new DynamicProperty("LastName", typeof(string));
int propIndex = 2;
foreach (var property in userProperties)
{
dynamicProperties[propIndex++] = new DynamicProperty(property, typeof(string));
}
Type resultType = ClassFactory.Instance.GetDynamicClass(dynamicProperties);
ConstructorInfo constructor = resultType.GetConstructor(new Type[] {});
object[] constructorParams = new object[] { };
PropertyInfo[] propInfoList = resultType.GetProperties();
PropertyInfo[] constantProps = propInfoList.Where(x => x.Name == "FirstName" || x.Name == "LastName").OrderBy(x => x.Name).ToArray();
IEnumerable<PropertyInfo> dynamicProps = propInfoList.Where(x => !constantProps.Contains(x));
// The actual dynamic results creation.
var dynamicResults = users.Select(user =>
{
object resultObject = constructor.Invoke(constructorParams);
constantProps[0].SetValue(resultObject, user.FirstName, null);
constantProps[1].SetValue(resultObject, user.LastName, null);
foreach (PropertyInfo propInfo in dynamicProps)
{
var val = user.UserPreferences.FirstOrDefault(x => x.Name == propInfo.Name);
if (val != null)
{
propInfo.SetValue(resultObject, val.UserValue, null);
}
}
return resultObject;
});
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// Display the results.
var displayResults = dynamicResults;
//var displayResults = results;
if (displayResults.FirstOrDefault() != null)
{
PropertyInfo[] properties = displayResults.First().GetType().GetProperties();
int columnWidth = Console.WindowWidth / properties.Length;
int index = 0;
foreach (PropertyInfo property in properties)
{
Console.SetCursorPosition(index++ * columnWidth, Console.CursorTop);
Console.Write(property.Name);
}
Console.WriteLine();
foreach (var result in displayResults)
{
index = 0;
foreach (PropertyInfo property in properties)
{
Console.SetCursorPosition(index++ * columnWidth, Console.CursorTop);
Console.Write(property.GetValue(result, null) ?? "(null)");
}
Console.WriteLine();
}
}
Console.WriteLine("\r\nPress any key to continue...");
Console.ReadKey();
}
static List<User> GetUserGroup()
{
List<User> users = new List<User>();
User user1 = new User();
user1.FirstName = "John";
user1.LastName = "Doe";
user1.UserPreferences = new List<UserPreference>();
user1.UserPreferences.Add(new UserPreference("Favorite color", "Red"));
user1.UserPreferences.Add(new UserPreference("Birthday", "Friday"));
User user2 = new User();
user2.FirstName = "Jane";
user2.LastName = "Doe";
user2.UserPreferences = new List<UserPreference>();
user2.UserPreferences.Add(new UserPreference("Favorite mammal", "Dolphin"));
user2.UserPreferences.Add(new UserPreference("Favorite color", "Blue"));
users.Add(user1);
users.Add(user2);
return users;
}

Categories