Selecting a property based on Name in Linq projection
I have a class say
public class CostStore
{
int DirectorateId { get; set; }
decimal NewCar { get; set; }
decimal ContractorNew { get; set; }
decimal ContractorRenew { get; set; }
decimal ContractorLost { get; set; }
decimal ContractorStolen { get; set; }
decimal InternalNew { get; set; }
decimal InternalRenew { get; set; }
decimal InternalLost { get; set; }
decimal InternalStolen { get; set; }
}
and in my controller i want to find out say
var c = from p in _service.List().Where (condition) p.InternalNew/InternalRenew
(etc) property based on a session variable like so in the function below, how can I do this in linq statement...any ideas (_service.List() lists the IEnumerable of the class CostStore
private string FindProperty()
{
switch (Session[Constants.FORMSESSIONKEY].ToString())
{
case Constants.NEWAPP:
return "InternalNew";
case Constants.LOST:
return "InternalLost";
case Constants.NEWCAR:
return "NewCar";
case Constants.OTHER:
return "InternalStolen";
case Constants.RENEW:
return "InternalRenew";
default:
return String.Empty;
}
}
Currently I am having to do this
private Decimal FindProperty()
{
switch (Session[Constants.FORMSESSIONKEY].ToString())
{
case Constants.NEWAPP:
return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
select p.InternalNew).Single() ?? 0.0M;
case Constants.LOST:
return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateI开发者_JS百科d)
select p.InternalLost).Single();
case Constants.NEWCAR:
return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
select p.NewCar).Single();
case Constants.OTHER:
return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
select p.InternalStolen).Single();
case Constants.RENEW:
return (from p in _costStoreService.List().Where(p => p.DirectorateId == _applicant.DirectorateId)
select p.InternalRenew).Single();
default:
return 0.0M;
}
}
but its a lot of duplicate code, also no check for sequence containing 0 values...
I'm assuming your service returns IQueryable<T>
. You can use an Expression to define projection outside of your query:
private Expression<Func<CostStore,Decimal>> GetProjection()
{
switch (Session[Constants.FORMSESSIONKEY].ToString())
{
case Constants.NEWAPP:
return c => c.InternalNew;
case Constants.LOST:
return c=> c.InternalLost;
// ... etc, you get the idea
default:
return c => 0m; // or some other sensible default
// break;
}
}
If your service returns IEnumerable<T>
, use Func<CostStore,decimal>
instead.
You can use it like this:
var projection = GetProjection();
var c = _service.List().Where (condition).Select(projection)
EDIT: put this in a console application, study and learn.
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication13
{
class Program
{
static void Main(string[] args)
{
var _service = new Service();
Func<CostStore, bool> condition = s => s.DirectorateId == 10;
Func<CostStore, decimal> projection = GetProjection();
var c = _service.List().Where(condition).Select(projection);
}
private static Func<CostStore, decimal> GetProjection()
{
return c => c.NewCar;
}
class Service
{
public IEnumerable<CostStore> List()
{
return new List<CostStore>();
}
}
public class CostStore
{
public int DirectorateId { get; set; }
public decimal NewCar { get; set; }
}
}
}
精彩评论