I am having an issue getting the value of a property to commit to the database. I have logic in my get statement that returns a value based on the value's from two other properties. The logic works correctly and displays the correct values in My Web Page, however the value for Rating Field is always set as Null in the database. My code below - if someone can point me in the right direction it would be greatly appreciated.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace PSA.Models
{
public class Issue
{
public virtual int IssueID { get; set; }
public virtual int ProbableClassificationId { get; set; }
public virtual ProbableClassification ProbableClassification { get; set; }
public virtual int SeverityClassificationId { get; set; }
public virtual SeverityClassification SeverityClassification { get; set; }
string ratingstatus;
public virtual string Rating
{
get
{
if (ProbableClassification != null && SeverityClassification != null)
{
if (SeverityClassification.Severity == "Minor")
{
ratingstatus = "Low";
}
if (ProbableClassification.Probability == "Not Likely" && SeverityClassification.Severity == "Medium")
{
ratingstatus = "Low";
}
if (ProbableClassification.Probability == "Likely" && SeverityClassification.Severity == "Medium")
{
ratingstatus = "Medium";
}
if (ProbableClassification.Probability == "Definitely" && SeverityClassification.Severity == "Medium")
{
ratingstatus = "Medium";
}
if (ProbableClassification.Probability == "Not Likely" && SeverityClassification.Severity == "Major")
{
ratingstatus = "Low";
}
if (ProbableClassification.Probability == "Likely" && SeverityClassification.Severity == "Major")
{
ratingstatus = "High";
}
if (ProbableClassification.Probability == "Definitely" && SeverityClassification.Severity == "Major")
{
ratingstatus = "Crtical";
}
}
return ratingstatus;
}
set
{
ratingstatus = value;
}
}
}
}
Related
I am working with some code that uses Columns.Add in conjunction with a lambda expression and would like to understand why/how it works. Here is a code snippet:
public ReportGrid(List<ReportRowDataContract> items)
: base(items)
{
if (items[0].ReportData1 != null)
{
if (items[0].ReportData1.DecimalValue != null)
{
Columns.Add(m => m.ReportData1.DecimalValue).Titled(items[0].ReportData1.Name).Encoded(false).
Sanitized(false).RenderValueAs(
m => (string.IsNullOrEmpty(#m.ReportData1.DisplayFormat)) ? Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString("N") : Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString(#m.ReportData1.DisplayFormat));
if (items[0].ReportData1.SumValue || items[0].ReportData1.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData1.Name,
AvgValue = items[0].ReportData1.AvgValue,
DecimalValue = 0
});
}
}
else if (items[0].ReportData1.IntValue != null)
{
Columns.Add(m => m.ReportData1.IntValue).Titled(items[0].ReportData1.Name);
if (items[0].ReportData1.SumValue || items[0].ReportData1.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData1.Name,
AvgValue = items[0].ReportData1.AvgValue,
IntValue = 0
});
}
}
else
{
Columns.Add(m => m.ReportData1.StringValue).Titled(items[0].ReportData1.Name);
}
}
if (items[0].ReportData2 != null)
{
if (items[0].ReportData2.DecimalValue != null)
{
Columns.Add(m => m.ReportData2.DecimalValue).Titled(items[0].ReportData2.Name).Encoded(false).
Sanitized(false).RenderValueAs(
m => (string.IsNullOrEmpty(#m.ReportData2.DisplayFormat)) ? Convert.ToDecimal(#m.ReportData2.DecimalValue).ToString("N") : Convert.ToDecimal(#m.ReportData2.DecimalValue).ToString(#m.ReportData1.DisplayFormat));
if (items[0].ReportData2.SumValue || items[0].ReportData2.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData2.Name,
AvgValue = items[0].ReportData2.AvgValue,
DecimalValue = 0
});
}
}
else if (items[0].ReportData2.IntValue != null)
{
Columns.Add(m => m.ReportData2.IntValue).Titled(items[0].ReportData2.Name);
if (items[0].ReportData2.SumValue || items[0].ReportData2.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = items[0].ReportData2.Name,
AvgValue = items[0].ReportData2.AvgValue,
IntValue = 0
});
}
}
else
{
Columns.Add(m => m.ReportData2.StringValue).Titled(items[0].ReportData2.Name);
}
}
This method consists of code that repeats itself out to ReportData6, changing only the ReportData field name with each repetition.
Here is the ReportRowDataContract class:
public class ReportRowDataContract
{
public ReportDataDataContract ReportData1 { get; set; }
public ReportDataDataContract ReportData2 { get; set; }
public ReportDataDataContract ReportData3 { get; set; }
public ReportDataDataContract ReportData4 { get; set; }
public ReportDataDataContract ReportData5 { get; set; }
public ReportDataDataContract ReportData6 { get; set; }
// an indexed property - for accessing report data fields by index
public ReportDataDataContract this[int i]
{
get
{
return new ReportDataDataContract[]
{
ReportData1,
ReportData2,
ReportData3,
ReportData4,
ReportData5,
ReportData6
}[i];
}
}
public int GetReportDataFieldCount()
{
return 6;
}
}
Unfortunately, I cannot change the structure of this class so I'm trying to convert the first code block into a method that loops. However, I'm stuck on what the Columns.Add is actually adding to.
Here is my code thus far:
public ReportGrid(List<ReportRowDataContract> items)
: base(items)
{
// get count of how many fields exist in ReportRowDataContract
int reportDataFieldCount = (new ReportRowDataContract()).GetReportDataFieldCount();
// create columns for grid for each field in ReportRowDataContract
//foreach (ReportRowDataContract item in items)
//{
int i = 0;
while (i < reportDataFieldCount)
{
AddGridColumn(items[0][i]);
i++;
}
//}
}
private void AddGridColumn(ReportDataDataContract reportColumn)
{
if (reportColumn != null)
{
if (reportColumn.DecimalValue != null)
{
Columns.Add(m => m.ReportData1.DecimalValue).Titled(reportColumn.Name).Encoded(false).
Sanitized(false).RenderValueAs(
m => (string.IsNullOrEmpty(#m.ReportData1.DisplayFormat)) ?
Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString("N") :
Convert.ToDecimal(#m.ReportData1.DecimalValue).ToString(#m.ReportData1.DisplayFormat));
if (reportColumn.SumValue || reportColumn.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = reportColumn.Name,
AvgValue = reportColumn.AvgValue,
DecimalValue = 0
});
}
}
else if (reportColumn.IntValue != null)
{
Columns.Add(m => m.ReportData1.IntValue).Titled(reportColumn.Name);
if (reportColumn.SumValue || reportColumn.AvgValue)
{
displaySummary = true;
SummaryData.Add(
new ReportDataDataContract
{
Name = reportColumn.Name,
AvgValue = reportColumn.AvgValue,
IntValue = 0
});
}
}
else
{
Columns.Add(m => m.ReportData1.StringValue).Titled(reportColumn.Name);
}
}
}
In the AddGridColumn method the part that is problematic is m => m.ReportData1. It's not dynamic so the first loop through is fine but on the second loop through an exception is thrown: System.ArgumentException {"Column 'ReportData1.StringValue' already exist in the grid"}. I know the m.ReportData1 needs to be changed or the approach modified...just don't know how to go about it.
Edit #1: Disabled the foreach per VitezslavSimon's insight. The same exception message is being thrown.
Edit #2: Base class of grid (I think).
public class Grid<T> : GridBase<T>, IGrid where T : class
{
public Grid(IEnumerable<T> items);
public Grid(IQueryable<T> items);
public IGridColumnCollection<T> Columns { get; }
public bool DefaultFilteringEnabled { get; set; }
public bool DefaultSortEnabled { get; set; }
public virtual int DisplayingItemsCount { get; }
public bool EnablePaging { get; set; }
public string Language { get; set; }
public IGridPager Pager { get; set; }
public GridRenderOptions RenderOptions { get; set; }
public ISanitizer Sanitizer { get; set; }
public override IGridSettingsProvider Settings { get; set; }
public virtual void AutoGenerateColumns();
protected internal virtual IEnumerable<T> GetItemsToDisplay();
}
It seems you need to add columns only once there. Try to help it by declaring a flag there. It also depends how your grid component is working behind.
Your code with draft of proposed change:
public ReportGrid(List<ReportRowDataContract> items)
: base(items)
{
// get count of how many fields exist in ReportRowDataContract
int reportDataFieldCount = (new ReportRowDataContract()).GetReportDataFieldCount();
// create columns for grid for each field in ReportRowDataContract
bool flag = true;
foreach (ReportRowDataContract item in items)
{
int i = 0;
if (flag) {
while (i < reportDataFieldCount)
{
AddGridColumn(items[0][i]);
i++;
}
flag = false;
}
}
}
I have these two EF classes:
class Row
{
public long CategoryId { get; set; }
public virtual Category Category { get; set; }
public long VesselId { get; set; }
public virtual Vessel Vessel { get; set; }
public int TruckType { get; set; }
}
class RowFilter
{
public long? CategoryId { get; set; }
public virtual Category Category { get; set; }
public long? VesselId { get; set; }
public virtual Vessel Vessel { get; set; }
public int? TruckType { get; set; }
public long? PortId { get; set; }
public virtual Port Port { get; set; }
public bool IsMatch(Row row)
{
if (CategoryId == null || CategoryId == row.CategoryId) {
if (VesselId == null || VesselId == row.VesselId) {
if (TruckType == null || TruckType == row.TruckType) {
if (PortId == null || PortId == row.Vessel.PortId) {
return true;
}
}
}
}
return false;
}
}
That is:
A Filter matches a Row if IsMatch() returns true for that row.
I have a list of rows, in an IQueryable manner:
var rows = dbContext.Rows.AsQueryable().Where(...);
...and for each row, I want to select (project) the row itself and the list of filters that match this row. I can do this easily in a Linq-to-Objects way ("in memory"):
// Linq-to-objects
rows.ToList().Select(r => new
{
row = r,
filters = dbContext.RowsFilters.Where(f => f.IsMatch(r))
};
Question is... is it possible to do it with Linq-to-Entities? (sql, not "in memory")
In a static world, I would have these navigation properties:
class Row
{
...
public virtual List<RowFilter> RowFilters { get; set; }
}
class RowFilter
{
...
public virtual List<Rows> Rows { get; set; }
}
but... that means a lot of updating: when creating a new RowFilter, when creating a new Row, etc.
You can do the following steps:
Modify the IsMatch method to return a Expression<Func<Row, bool>> type and implement it like this :
public Expression<Func<Row, bool>> IsMatch()
{
Expression<Func<Row, bool>> filter = r => (CategoryId == null || CategoryId == r.CategoryId)
&& (VesselId == null || VesselId == r.VesselId)
&& (TruckType == null || TruckType == r.TruckType)
&& (PortId == null || PortId == r.PortId);
return filter;
}
Then just use it like this :
var rowFilter = new RowFilter { PortId = 1, CategoryId = 2, TruckType = 3, VesselId = 4 };
var query = context.Rows.Where(rowFilter.IsMatch());
All the linq are translated into SQL then executed on the server side. The generated SQL by EF looks like the following:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[CategoryId] AS [CategoryId],
[Extent1].[VesselId] AS [VesselId],
[Extent1].[TruckType] AS [TruckType],
[Extent1].[PortId] AS [PortId]
FROM [dbo].[Rows] AS [Extent1]
WHERE (#p__linq__0 IS NULL OR #p__linq__1 = [Extent1].[CategoryId]) AND (#p__linq__2 IS NULL OR #p__linq__3 = [Extent1].[VesselId]) AND (#p__linq__4 IS NULL OR #p__linq__5 = [Extent1].[TruckType]) AND (#p__linq__6 IS NULL OR #p__linq__7 = CAST( [Extent1].[PortId] AS bigint))
You can use the following query:
var query = from r in context.Rows
from f in context.RowFilters.Where(f =>
(f.CategoryId == null || f.CategoryId == r.CategoryId) &&
(f.VesselId == null || f.VesselId == r.VesselId) &&
(f.TruckType == null || f.TruckType == r.TruckType) &&
(f.PortId == null || f.PortId == r.Vessel.PortId))
.DefaultIfEmpty()
let x = new {r, f}
group x by x.r
into gr
select new
{
row = gr.Key,
filters = gr.Select(y => y.f).Where(yf => yf != null)
};
var result = query.ToList();
Here is an alternative syntax:
var query = context.Rows
.SelectMany(r =>
context.RowFilters.Where(f =>
(f.CategoryId == null || f.CategoryId == r.CategoryId) &&
(f.VesselId == null || f.VesselId == r.VesselId) &&
(f.TruckType == null || f.TruckType == r.TruckType) &&
(f.PortId == null || f.PortId == r.Vessel.PortId))
.DefaultIfEmpty()
.Select(f => new {r, f}))
.GroupBy(x => x.r)
.Select(x => new
{
row = x.Key,
filters = x.Select(y => y.f).Where(yf => yf != null)
});
I have two custom classes.
The first class contains basic data:
public class Request
{
public Request(int lineID, string partNo, int qty, int reasonID, int typeID)
{
LineID = lineID;
PartNo = partNo;
Qty = qty;
ReasonID = reasonID;
TypeID = typeID;
}
public int LineID { get; private set; }
public string PartNo { get; private set; }
public int Qty { get; internal set; }
public int ReasonID { get; private set; }
public int TypeID { get; private set; }
}
The second class contains a List of these Request objects, with a signature as follows:
public class Requests : IEnumerable<Request>
{
private List<Request> list;
public Requests()
{
list = new List<Request>();
}
public int Add(Request item)
{
if (item != null)
{
foreach (var x in list.Where(r =>
(r.LineID == item.LineID) &&
(r.PartNo == item.PartNo) &&
(r.ReasonID == item.ReasonID) &&
(r.TypeID == item.TypeID)))
{
x.Qty += item.Qty;
return list.IndexOf(x);
}
list.Add(item);
return list.Count - 1;
}
return -1;
}
// other code
}
I am testing my code and adding items is putting new items into the list, but the LINQ query to find duplicates is not working.
If 2 identical items are added to the list, I want my code to be smart enough to simply update the quantity, but it does not seem to be working.
Could someone tell me what is wrong with the LINQ query?
Could someone tell me what is wrong with the LINQ query?
Theoretically it looks OK. I think we need to know more information about your data to be able to find out why it isn't working as you expect. Does the combination of LineID, PartNo, ReasonID, and TypeID uniquely distinguish an item? Since PartNo is a string, are the values case-insensitive (your comparison is case-sensitive)?
If 2 identical items are added to the list, I want my code to be smart enough to simply update the quantity, but it does not seem to be working.
For this I would suggest a different approach. Consider overriding Equals() on your Request type. Then your Add method can just check if the list already contains the item, incrementing the quantity if so and adding it if not:
var idx = list.IndexOf(item);
if(idx != -1)
{
list[idx].Qty += item.Qty;
}
else
{
list.Add(item);
}
Make Request implement IEquatable<Request>, because this is what IndexOf uses:
public bool Equals(Request other) {
return other != null && (this.LineID == other.LineID) && (this.PartNo == other.PartNo) && (this.ReasonID == other.ReasonID) && (this.TypeID == other.TypeID);
}
Then:
public int Add(Request item) {
if (item != null)
{
int ind = list.IndexOf(item);
if (ind == -1)
{
list.Add(item);
return list.Count - 1;
}
else
{
list[ind].Qty += item.Qty;
return ind;
}
}
return -1;
}
You can modify the method by materializing LINQ query. For example:
public int Add(Request item) {
if (item != null) {
foreach (var x in list.Where(r =>
(r.LineID == item.LineID) &&
(r.PartNo == item.PartNo) &&
(r.ReasonID == item.ReasonID) &&
(r.TypeID == item.TypeID)
).ToList()) {
x.Qty += item.Qty;
return list.IndexOf(x);
}
list.Add(item);
return list.Count - 1;
}
return -1;
}
But, because your Requests must be unique, you can use this
public int Add(Request item)
{
if (item != null)
{
var req = list.SingleOrDefault(r =>
(r.LineID == item.LineID) &&
(r.PartNo == item.PartNo) &&
(r.ReasonID == item.ReasonID) &&
(r.TypeID == item.TypeID)
);
if(req!=null)
{
req.Qty += item.Qty;
return list.IndexOf(req);
}
list.Add(item);
return list.Count - 1;
}
return -1;
}
I have to run comparisons between thousands of pairs of objects, and then perform actions depending on the differences.
Is there an "accepted" way of doing this?
class ObjectA
{
public string FieldA { get; set; }
public string FieldB { get; set; }
public string FieldC { get; set; }
}
class ObjectB
{
public string FieldA { get; set; }
public string FieldB { get; set; }
public string FieldC { get; set; }
public bool Equals(ObjectA obj)
{
if ((object)obj == null) return false;
if (this.FieldA != obj.FieldA) return false;
if (this.FieldB != obj.FieldB) return false;
if (this.FieldC != obj.FieldC) return false;
return true;
}
}
void test()
{
ObjectA a = new ObjectA();
ObjectB b = new ObjectB();
if (b.Equals(a))
{
Console.WriteLine("Same!!");
}
}
That does a fairly simple test to determine if b=a, but I also want to know what is different between them.
Should I add a differences() method that returns a list of properties? That seems a bit not.net though, as then I'll be bandying about strings.
public List<string> Differences(ObjectA obj)
{
List<string> differences = new List<string>();
if ((object)obj == null)
{
differences.Add("null");
}
else
{
if (this.FieldA != obj.FieldA) differences.Add("FieldA");
if (this.FieldB != obj.FieldB) differences.Add("FieldB");
if (this.FieldC != obj.FieldC) differences.Add("FieldC");
}
return differences;
}
Also that seems much slower than the first, as I would be creating all those List<string>, and not short-cutting the comparisons. Or is that just the price I pay for having the extra information?
Maybe you should try this:
http://comparenetobjects.codeplex.com/
All credit to the author...
Edit: Since codeplex is shutting down, the github url : https://github.com/GregFinzer/Compare-Net-Objects
There is nothing built in that will allow you to represent partial objects (i.e the differences).
Your approach seems reasonable for what you are trying to achieve.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
class ObjectA
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public string PropertyC { get; set; }
public DateTime PropertyD { get; set; }
public string FieldA;
public DateTime FieldB;
}
class ObjectB
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public string PropertyC { get; set; }
public DateTime PropertyD { get; set; }
public string FieldA;
public DateTime FieldB;
}
class Program
{
static void Main(string[] args)
{
// create two objects with same properties
ObjectA a = new ObjectA() { PropertyA = "test", PropertyB = "test2", PropertyC = "test3" };
ObjectB b = new ObjectB() { PropertyA = "test", PropertyB = "test2", PropertyC = "test3" };
// add fields to those objects
a.FieldA = "hello";
b.FieldA = "Something differnt";
if (a.ComparePropertiesTo(b))
{
Console.WriteLine("objects have the same properties");
}
else
{
Console.WriteLine("objects have diferent properties!");
}
if (a.CompareFieldsTo(b))
{
Console.WriteLine("objects have the same Fields");
}
else
{
Console.WriteLine("objects have diferent Fields!");
}
Console.Read();
}
}
public static class Utilities
{
public static bool ComparePropertiesTo(this Object a, Object b)
{
System.Reflection.PropertyInfo[] properties = a.GetType().GetProperties(); // get all the properties of object a
foreach (var property in properties)
{
var propertyName = property.Name;
var aValue = a.GetType().GetProperty(propertyName).GetValue(a, null);
object bValue;
try // try to get the same property from object b. maybe that property does
// not exist!
{
bValue = b.GetType().GetProperty(propertyName).GetValue(b, null);
}
catch
{
return false;
}
if (aValue == null && bValue == null)
continue;
if (aValue == null && bValue != null)
return false;
if (aValue != null && bValue == null)
return false;
// if properties do not match return false
if (aValue.GetHashCode() != bValue.GetHashCode())
{
return false;
}
}
return true;
}
public static bool CompareFieldsTo(this Object a, Object b)
{
System.Reflection.FieldInfo[] fields = a.GetType().GetFields(); // get all the properties of object a
foreach (var field in fields)
{
var fieldName = field.Name;
var aValue = a.GetType().GetField(fieldName).GetValue(a);
object bValue;
try // try to get the same property from object b. maybe that property does
// not exist!
{
bValue = b.GetType().GetField(fieldName).GetValue(b);
}
catch
{
return false;
}
if (aValue == null && bValue == null)
continue;
if (aValue == null && bValue != null)
return false;
if (aValue != null && bValue == null)
return false;
// if properties do not match return false
if (aValue.GetHashCode() != bValue.GetHashCode())
{
return false;
}
}
return true;
}
}
As long as the names of the properties are equal, you can do this using the property map of each object and linq. I've done this in the past, but I don't have the code in front of me at the moment, sorry.
Here's an example I used for unit testing two instances of the same object type. I was testing to ensure that the properties that were serialized to file and populated in a new instance of the same object type were the same. Note that this is using System.Reflection and that you are comparing instances of the same type.
//Assume yourobjectA and yourobjectB have already been instantiated and populated.
//loop throught he properties and compare
//they should all be set the same as the previous instance
PropertyInfo[] propertiesA = yourobjectA.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] propertiesB = yourobjectB.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
int count = oldProperties.Length;
for (int i = 0; i < count; i++)
{
if ((propertiesA [i].CanRead) && (propertiesB [i].CanRead))
{
if (propertiesA [i].PropertyType == typeof(String))
{
object oldStringValue = (string)propertiesA[i].GetValue(yourobjectA, null);
object newStringValue = (string)propertiesB[i].GetValue(yourobjectB., null);
if(oldStringValue != newStringValue )
{
//Do something
}
}
if (propertiesA [i].PropertyType == typeof(Boolean))
{
object oldBoolValue = (bool)propertiesA [i].GetValue(yourobjectA, null);
object newBoolValue = (bool)propertiesB [i].GetValue(yourobjectB., null);
if(oldBoolValue != newBoolValue)
{
//Do something
}
}
}
}
I have to test the equality of trees. In other other words objects which contains List<T> with childs and the childs also contains List<T> with childs and so on.
I've found that you can test List with CollectionAssert, however it does not work that well with composites.
Any suggestions? MSUnit is my test library.
Example
IReagentComposed bronzeBarParsed = (from n in composedCrafts where n.ItemId == 2841 select n).Single();
IReagentComposed bronzeBar = new Craft()
{
ItemId = 2841,
Profession = Profession.Mining,
Quantity = 0,
QuantityCrafted = 0,
Skill = 50,
Reagents = new List()
{
new Craft()
{
ItemId = 2840,
Quantity = 0,
Skill = 1,
Profession = Profession.Mining,
Reagents = new List()
{
new Reagent()
{
ItemId = 2770,
Quantity = 1
}
}
},
new Craft()
{
ItemId = 3576,
Quantity = 0,
Skill = 50,
Profession = Profession.Mining,
Reagents = new List()
{
new Reagent()
{
ItemId = 2771,
Quantity = 1
}
}
}
}
};
Assert.AreEqual(bronzeBar, bronzeBarParsed);
Craft and Reagent
public class Craft : IReagentComposed
{
public int QuantityCrafted { get; set; }
public int Quantity { get; set;}
public int ItemId { get; set; }
public int Skill { get; set; }
public Profession Profession { get; set; }
public IEnumerable Reagents { get; set; }
public override bool Equals(object other)
{
if (other == null || GetType() != other.GetType()) return false;
IReagentComposed o = other as IReagentComposed;
return o != null && this.Quantity == o.Quantity &&
this.ItemId == o.ItemId &&
this.Profession == o.Profession &&
this.Reagents == o.Reagents && //also tried Equals
this.Skill == o.Skill;
}
public override int GetHashCode()
{
return 0;
}
}
public class Reagent : IReagent
{
public int ItemId { get; set; }
public int Quantity { get; set; }
public override bool Equals(object other)
{
if (other == null || GetType() != other.GetType()) return false;
IReagent o = other as IReagent;
return o != null && o.ItemId == this.ItemId && o.Quantity == this.Quantity;
}
public override int GetHashCode()
{
return 0;
}
}
return o != null && this.Quantity == o.Quantity &&
this.ItemId == o.ItemId &&
this.Profession == o.Profession &&
this.Reagents == o.Reagents && //also tried Equals
this.Skill == o.Skill;
The Reagents are unlikely to match, they are distinct List objects. List<> doesn't override Equals although it isn't that clear what actual type you use. Write a little helper function that takes two lists of reagents and checks for equality. You'd typically start at comparing List<>.Count and then work down the elements one by one.
Added a extension method for IEnumberable<T>:
public static class IEnumberableExtensions
{
public static bool AreEnumerablesEqual<T>(this IEnumerable<T> x, IEnumerable<T> y)
{
if (x.Count() != y.Count()) return false;
bool equals = false;
foreach (var a in x)
{
foreach (var b in y)
{
if (a.Equals(b))
{
equals = true;
break;
}
}
if (!equals)
{
return false;
}
equals = false;
}
return true;
}
}