How to get total Sum of my Collection/Class - c#

I have this class:
public class ExtraDisplayItems
{
public int ItemId { get; set; }
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
public double? ItemSellingPrice { get; set; }
}
I then add data to the class with the method below:
using (TruckServiceClient TSC = new TruckServiceClient())
{
var item = cmbAddExtras.SelectedItem as ExtraDisplayItems;
if (item != null)
{
var displayItem = new List<ExtraDisplayItems>
{
new ExtraDisplayItems
{
ItemId = item.ItemId,
ItemCode = item.ItemCode,
ItemDescription = item.ItemDescription,
ItemSellingPrice = item.ItemSellingPrice
}
};
dgAddExtras.Items.Add(item);
}
}
Now what I want to do is create a read-only property where I would get the total Sum of the ItemSellingPrice, but in this property I cannot reach the Sum when trying to calculate the double?
This is how I wan't the coding to work:
public double? SubTotalExtras
{
get { return ExtraDisplayItems.Sum(x => x.ItemSellingPrice); }
}
But... it's giving me the error:
ExtraDisplayItems does not contain a definition for 'Sum'
How would I go about fixing this?
EDIT
I have changed the class to:
public class ExtraDisplayItems
{
private List<ExtraDisplayItems> displayItems;
public int ItemId { get; set; }
...
}
And...
if (item != null)
{
this.displayItems = new List<ExtraDisplayItems> //Error
{
new ExtraDisplayItems
{
...
}
};
dgAddExtras.Items.Add(item);
}
But it now throws the error: does not contain definition for 'displayItems'

It seems dat ExtraDisplayItems is an instance of the ExtraDisplayItems class, which doesn't implement IEnumerable<T> (that is: 'it is a collection of something'). That means that it indeed doesn't have a Sum method, nor does the extension method apply.
My best guess at the moment is that you should save the displayItem (which is a List<ExtraDisplayItems>, so it implements IEnumerable<ExtraDisplayItems>) somewhere in your view model and call Sum on that.
Also, use naming conventions: you are making plurals singular and the other way around... Very confusing...

You are probably missing Linq in your using definitions.
using System.Linq;
EDIT:
I was assuming ExtraDisplayItems was a collection, then it is common to have the error 'x does not contain a definition for 'Sum'' even if you see it in code samples.
In order to do the sum various objects you actually need a collection of them not a single object.

Related

System.Reflection.TargetException on employee.GetType().GetProperty(property.Name)

I have come upon an issue I can't seem to figure out. I'm sure there's a simple explanation to this, but I don't understand why I get a System.Reflection.TargetException: 'Object does not match target type' when I try to get a property from (in this case) the employee object.
employee.GetType().GetProperty(property.Name)
Searching for the error returns many results describing problems with calling the Set/GetValue methods, but I haven't found a solution to this one.
I've set a breakpoint where the exception is thrown and it shows that property.Name is indeed a value - and a real property of the object. I've also tried manually specifying a property I know exists. Still the same.
Any suggestions?
EDIT: Tried the following instead:
Type type = typeof (Employee); //Throws the TargetException
PropertyInfo theProperty = type.GetProperty(property.Name);
And now the same exception is thrown at the first line above instead.
EDIT: Added code and more details about the application I'm building.
Class definition for Employee (to simplify mapping to the JSON data this class "represents", the class/fields are in Norwegian - which is the format/language the data comes in, sorry :-).)
"Ansatt" = Employee. "Ansattnummer" = EmployeeNo.
[JsonObject]
public class Ansatt
{
public int Ansattnummer { get; set; }
public string Fornavn { get; set; }
public string Etternavn { get; set; }
public int Pin { get; set; }
public string Adresse { get; set; }
public int Postnummer { get; set; }
public string Poststed { get; set; }
public int TlfPrivat { get; set; }
public int MobilTlf { get; set; }
public string EpostAdresse { get; set; }
public DateTime Fodt { get; set; }
}
My application retrieves a given dataset from a web service - it could be employees, projects or a few other possible datasets. What data to fetch is determined at runtime - by the user. The user can also specify via URL-query which portions, e.g. columns, of the dataset he/she wants. The program then creates a csv-file with the selected data.
Here's the code I use for this:
if (records != null && records.Count != 0) //records contains the chosen dataset - in this case Employees (Ansatt).
{
if (records.GetType() == typeof (List<Ansatt>))
{
foreach (var model in records as List<Ansatt>)
{
var temp = new Ansatt();
foreach (var property in model.GetType().GetProperties())
{
var currentProperty = model.GetType().GetProperty(property.Name);
if (currentProperty != null)
{
Type type = typeof (Ansatt); //Throws System.Reflection.TargetException: 'Object does not match target type'
PropertyInfo tempProperty = type.GetProperty(property.Name);
tempProperty.SetValue(temp, currentProperty.GetValue(property.Name));
}
}
csv.WriteRecord(temp);
}
}
}
You need to specify the name of the property
PropertyInfo value = employee.GetType().GetProperty("Name");
As MSDN goes, you should use it this way:
class MyClass {
private int myProperty;
// Declare MyProperty.
public int MyProperty {
get {
return myProperty;
}
set {
myProperty = value;
}
}
}
public class MyTypeClass {
public static void Main(string[] args) {
try {
// Get the Type object corresponding to MyClass.
Type myType = typeof(MyClass);
// Get the PropertyInfo object by passing the property name.
PropertyInfo myPropInfo = myType.GetProperty("MyProperty");
// Display the property name.
Console.WriteLine("The {0} property exists in MyClass.", myPropInfo.Name);
// Instantiate MyClass
var myObject = new MyClass()
{
MyProperty = 5
};
// Get value using reflection
Console.WriteLine("My property value for my object is {0}.", myPropInfo.GetValue(myObject));
} catch (NullReferenceException e) {
Console.WriteLine("The property does not exist in MyClass." + e.Message);
}
}
}
For your code, when you want to get the property value of an object instance, you should pass object as reference to PropertyInfo.GetValue(object) function.
Instead of this:
tempProperty.SetValue(temp, currentProperty.GetValue(property.Name));
Do this:
tempProperty.SetValue(temp, currentProperty.GetValue(model));
For you to get the property of object through reflection, make it sure that the property name is public with getter and setter else it will return null.
Ex.
public class Employee
{
public string YouProperty { get; set; }
}
var employee = new Employee();
var result = employee.GetType().GetProperty("YouProperty");
// The result is property info
Kindly read some information here.

Using Reflection and GetValue problems

I have an abstract class that looks like so:
public abstract class PageObjectsBase
{
public abstract string FriendlyName { get; }
public abstract string PageObjectKeyPrefix { get; }
public abstract string CollectionProperty { get; }
}
And a class that derives from PageObjectsBase:
public class PageRatingList : PageObjectsBase
{
public IList<PageRating> PageRatings { get; set; }
public PageRatingList()
{
this.PageRatings = new List<PageRating>();
}
public override string CollectionProperty
{
get
{
var collectionProperty = typeof(PageRatingList).GetProperties().FirstOrDefault(p => p.Name == "PageRatings");
return (collectionProperty != null) ? collectionProperty.Name : string.Empty;
}
}
public override string FriendlyName
{
get
{
return "Page feedback/rating";
}
}
public override string PageObjectKeyPrefix
{
get
{
return "pagerating-";
}
}
}
And a PageRating class which PageRatingList.PageRatings is holding a collection of:
public class PageRating : PageObjectBase
{
public int Score { get; set; }
public string Comment { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
The PageRatingList is being stored in a database (EPiServer's Dynamic Data Store, more specifically using the Page Object Manager). I need to create some reporting functionality and am essentially loading all reports that derive from PageObjectBase. When it comes to returning the data, the code will never know at compile time what type of data it is to load, so I am using Reflection. In my reporting class I have:
//this gives me the right type
var type = Type.GetType("MyNameSpace.PageRatingList", true);
var startPageData = this._contentRepository.Get<PageData>(startPage);
PageObjectManager pageObjectManager = new PageObjectManager(startPageData);
//this loads the instances from the DB
var props = pageObjectManager.LoadAllMetaObjects()
.FirstOrDefault(o => o.StoreName == "Sigma.CitizensAdvice.Web.Business.CustomEntity.PageRatingList");
//this gives me 4 PropertyInfo objects (IList: PageRatings, string : CollectionProperty, string :FriendlyName, string : PageObjectKeyPrefix)
var properties = props.Value.GetType().GetProperties();
I can then iterate through the PropertyInfo objects using:
foreach (var property in properties)
{
//extract property value here
}
The issue I am having is that I cannot figure out how to get the value of each of the propertyinfo objects. In addition, one of those properties is type List and again we wont know the type of T until runtime. So I also need some logic that checks if one of the PropertyInfo objects is of type List and then provides access to each of the properties in the List - the List being of type PageRating.
Can anyone help here? I've not really used reflection in the past so I am winging my way through it, rightly or wrongly!
Many thanks
Al
I may be missunderstanding the problem, but i think you may use something like this:
var props = new PageRatingList(); /*actual instanse of the object, in your case, i think "props.Value" */
var properties = typeof(PageRatingList).GetProperties();
foreach (var property in properties)
{
if (property.PropertyType == typeof(IList<PageRating>))
{
IList<PageRating> list = (IList<PageRating>)property.GetValue(props);
/* do */
}
else
{
object val = property.GetValue(props);
}
}
Hope this helps to find your solution.

Linq query condition on self-referencing entity

I am trying to retrieve all entities of type Queried from the database where Referenced property or it's ancestor for which its label (meaning referenced.Parent.ChildLabel) is equal to some given label value exampleLabel, has an Id equal to exampleId.
I tried using:
var result = nhibernateSession
.Query<Queried>()
.Where(queried => queried.SelfReferencing.GetSelfOrAncestor("exampleLabel") == exampleId)
.ToList();
but it throws a "System.NotSupportedException", probably because it does not know how to translate the GetSelfOrAncestor into SQL.
The method GetSelfOrAncestor(string label) returns the Id of the SelfReferencing instance on which it was called or it's ancestor which meets the condition that this.Parent.ChildLabel is equal to exampleLabel, otherwise returns 0.
For example, in the following diagram if queried.SelfReferencing would point to the one at Level 2, GetSelfOrAncestor("exampleLabel") would return the Id of the object at Level 1.
http://j.mp/Xl86OP
public class Queried
{
public int Id { get; set; }
public SelfReferencing Referenced { get; set; }
}
public class SelfReferencing
{
public SelfReferencing Parent { get; set; }
private IList<SelfReferencing > children = new List<SelfReferencing >();
public virtual IList<SelfReferencing > Children
{
get
{
return children;
}
set
{
children = value;
}
}
public string ChildLabel { get; set; }
}
Any help on how to achieve this would be highly appreciated :)
To achieve what you want, I would provide a method in SelfReferencing that does the search for the label through the object graph.
Should be something like this: (Warning, not tested yet!)
public bool ContainsLabel(string label)
{
if (this.ChildLabel.Equals(label))
{
return true;
}
else
{
foreach (var child in Children)
{
return child.ContainsLabel(label);
}
}
return false;
}
You can use it then as follows:
var result = nhibernateSession
.Query<Queried>()
.Where(queried => queried.SelfReferencing.ContainsLabel("exampleLabel"))
.ToList();
Edited for more convenience in reading.

linq - retrieving data dependent on the object type

I have a structure like this
public class ItemBase
{
public int ItemId { get; set; }
public DateTime Created { get; set; }
public ItemType Type { get; set; }
}
public class RockItem : ItemBase { }
public class PlantItem : ItemBase
{
public bool IsDeadly { get; set; }
}
public class AnimalItemBase : ItemBase
{
public int NumberOfLegs { get; set; }
public bool IsDeadly { get; set; }
}
public class DogItem : AnimalItemBase { }
public class CatItem : AnimalItemBase { }
There is a type flag in the database and I use Fluent to split out on type and return an IEnumerable<ItemBase>
This works for most of what I want, but now I am in a situation where I need to meld the items together. For instance, I want the ItemId, IsDeadly, and the NumberOfLegs returned in an anonymous object. The results have to be sorted on the Created field in one list. Is there an easy way to do this with linq? Ideally, I would not have to split these out, merge the results, and then sort.
The example you give could be solved using OfType:
IEnumerable<ItemBase> items = ...
var results = items.OfType<AnimalItemBase>()
.OrderBy(x => x.Created).ToList();
If you have to support combinations of properties that cross classes i.e all items that have the IsDeadly property, you could use a combination of reflection to check the properties you want to use and dynamic to enable the duck typing you need, since technically these are different IsDeadly properties, you just know they should be treated the same in your scenario.
Doing that you can then assign the properties in your anonymous type dynamically. I.e. the following example returns results for all of your types that have the IsDeadly property:
var results = items.OrderBy(x => x.Created)
.Where(x => x.GetType().GetProperty("IsDeadly") !=null)
.Select( x =>
{
dynamic o = x;
return new { IsDeadly = o.IsDeadly, Created = o.Created };
})
.ToList();
Also as #Henk Holterman pointed out, it only makes sense to return an enumeration of anonymous types where each property of the returned type makes sense / is defined for all the items in the enumeration.

Databind a List with a Template to a Dropdown Datasource

I have a Template via:
public class OwnedProvinces
{ public Guid ProvinceID;
public string ProvinceName;
}
And I created a list with this template here:
List<OwnedProvinces> getinfo = (from upi in db.Utopia_Province_Data_Captured_Gens
where upi.Owner_User_ID == SQLStatementsCS.UserID()
where upi.Province_Name != string.Empty
select new OwnedProvinces { ProvinceName = upi.Province_Name, ProvinceID = upi.Province_ID}).ToList();
The problem with this when I try to bind it to the Dropdown list like so:
ddlSelectProvince.DataTextField = "ProvinceName";
ddlSelectProvince.DataValueField = "ProvinceID";
ddlSelectProvince.DataSource = getinfo;
ddlSelectProvince.DataBind();
It throws the Error:
DataBinding: 'OwnedProvinces' does not contain a property with the name 'ProvinceName'.
Basically, it can't find the property ProvinceName in the List, but makes no sense to me. If I do an anonymous query, it works, but when I assign it to the class OwnedPRovinces, it throws this error...
Try to change the class like this
public class OwnedProvinces
{
public Guid ProvinceID { get; set; }
public string ProvinceName { get; set; }
}
The problem is that ProvinceID and ProvinceName are member variables not properties.
Problem is with your declaration -
public Guid ProvinceID;
public string ProvinceName;
are the fields, but not the properties. You should either change their definition or you should try to implement the IDataBindable interface, as written here:
http://www.primaryobjects.com/CMS/Article95.aspx
#region IDataBindable Members
public List<NameValueType> ToList()
{
List<NameValueType> resultList = new List<NameValueType>();
using (DataContext context = new DataContext())
{
List<Monster> itemList = context.Monsters.ToList();
foreach (Monster item in itemList)
{
resultList.Add(new NameValueType(item.MonsterId.ToString(), item.Name));
}
}
return resultList;
}
#endregion

Categories