How can I compare two lists with xunit test - c#

I am currently trying to compare two lists, with the same items in it, with xUnit but getting an error while running.
Assert.Equal(expectedList, actualList);
Error:
"Assert.Equal() Failure"
Expected: List<myObject> [myObject { modifier = '+', name = "name", type = "string" }, myObject { modifier = '+', name = "age", type = "int" }]
Actual: List<myObject> [myObject { modifier = '+', name = "name", type = "string" }, myObject { modifier = '+', name = "age", type = "int" }]

This has to do with object equality.
MyObject does not implement the Equals method. By default you get a reference equality. I assume you have two different objects for MyObject.
Meaning it does not matter that your List holds the similar object(meaning with same values) they are not of the same reference, so your test checks that, this is why it fails.
internal class MyObject
{
{
public char Modifier { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
}
[Fact]
public void ListMyObject()
{
var list1 = new List<MyObject>
{
new MyObject{ }
};
var list2 = new List<MyObject>
{
new MyObject{ }
};
Assert.Equal(list1, list2); // Fails
}
When we update our class to this.
internal class MyObject
{
public char Modifier { get; set; }
public string Name { get; set; }
public string Type { get; set; }
//When i add this to my class.
public override bool Equals(object obj)
{
return this.Name == ((MyObject)obj).Name;
}
}
Also as mentioned in the comments by Jonathon Chase.
It is a good idea to override the GetHashCode() method as well. It is preferred to inherit from IEquatable<T> so you can avoid casting.
Everything goes green.
[Fact]
public void ListMyObject()
{
var list1 = new List<MyObject>
{
new MyObject{ Name = "H" }
};
var list2 = new List<MyObject>
{
new MyObject{ Name = "H" }
};
Assert.Equal(list1, list2); //Passes
}

Related

How to make nested foreach loop method generic

I want to get a list of all (unique) Apple (or Oranges) objects:
var theBigFruitsList = new List<Fruits>{
new Fruits(){
Apples = new List<Apple>{
new Apple { Id = 1 },
new Apple { Id = 2 }
}
},
Oranges = new List<Orange>{
new Orange { Id = 4 },
new Orange { Id = 5 }
}
},
FruitBoolean = False,
FruitCount = 4,
},
new Fruits(){
Apples = new List<Apple>{
new Apple { Id = 3 },
new Apple { Id = 1 },
}
},
Oranges = new List<Orange>{
new Orange { Id = 6 },
}
}
FruitBoolean = False,
FruitCount = 3,
}
}
I have written this method for it:
public static List<Apple> GetApplesFromBigFruitsList(List<Fruits> theBigFruitsList )
{
var dc = new Dictionary<long, Apple>();
foreach (var fruits in theBigFruitsList)
{
foreach (var apple in fruits.Apples)
{
if (!dc.ContainsKey(apple.Id))
dc.Add(apple.Id, apple);
}
}
return dc.Values.ToList();
}
But as besides Apples and Oranges there are many other types of 'Fruits' in that object, I have that method more then 10 times where the word Apple is just replaced with Orange.. It would make sense to make it generic.
I wrote this function but it gives an error as Fruits class does not implement an enumerator. Please help!
public static List<T> FilterFruits<T>(T typeToGet, List<Fruits> theBigFruitsList)
{
List<T> fruitResult = new List<T>();
var fruitType = typeToGet.GetType();
foreach (var fruits in theBigFruitsList)
{
foreach (var fruit in fruits) //errors, intention is to loop over all properties in the Fruits entity to find one specific type
if (fruit.GetType() == fruitType) //check if type is Apple
{
fruitResult.AddRange(fruits); //add the Apples to a list
}
}
return fruitResult;
}
The classes:
public class Fruits{
public List<Apple> Apples { get; set; }
public List<Orange> Oranges { get; set; }
public List<Pineapple> Pineapples { get; set; }
public List<Mango> Mangos { get; set; }
public bool FruitBoolean { get; set; }
public long FruitCount { get; set; }
}
public class Apple{
public long Id { get; set; }
}
public class Orange{
public long Id { get; set; }
}
public class Pineapple{
public long Id { get; set; }
}
public class Mango{
public long Id { get; set; }
}
The desired method result:
var Apples = List<Apple>{
new Apple { Id = 1 },
new Apple { Id = 2 },
new Apple { Id = 3 }
}
With One Big List
Storing each type of fruit in its own separate list is...weird. I suggest you combine them in a single list. If you can't change the design, you can combine them at run time like this:
IEnumerable<object> GetAllFruits(Fruits bigFruitlist)
{
return ((IEnumerable<object>)bigFruitlist.Apples)
.Concat((IEnumerable<object>)bigFruitlist.Oranges)
.Concat((IEnumerable<object>)bigFruitlist.Mangoes)
.Concat((IEnumerable<object>)bigFruitlist.Pineapples);
}
Of course it would be way better if all of your fruits had a common interface-- then you wouldn't need IEnumerable<object>-- but this can still work if you can't make that change either.
Once you have the combined list, the rest is easy:
List<T> FilterFruits<T>(Fruits bigFruitlist)
{
return GetAllFruits(bigFruitList).OfType<T>().ToList();
}
With an Array of Lists
If there is some reason you want to avoid enumerating all of the lists (i.e. the lists are massive and performance is a concern), you can also do it with an array of lists.
object[] GetAllFruitLists(Fruits bigFruitlist)
{
return new object[]
{
bigFruitlist.Apples,
bigFruitlist.Oranges,
bigFruitlist.Mangoes,
bigFruitlist.Pineapples
};
}
List<T> FilterFruits<T>(Fruits bigFruitlist)
{
return GetAllFruitLists(bigFruitList).OfType<List<T>>().Single();
}
To interrogate an object's type at runtime use Reflection. Like this:
public static List<T> FilterFruits<T>(List<Fruits> fruitsList) where T : IFruit
{
List<T> fruitResult = new List<T>();
var fruitType = typeof(T);
foreach (var fruits in fruitsList)
{
foreach (var fp in typeof(Fruits).GetProperties())
{
if (fp.PropertyType == typeof(List<T>)) //check if type is Apple
{
fruitResult.AddRange((List<T>)(object)fp.GetValue(fruits)); //add the Apples to a list
}
}
}
return fruitResult;
}
(T)(object)o is the C# idiom for performing a cast that can't by verified by the compiler, and may possibly fail at runtime, which we know that it won't but the compiler can't because it doesn't understand Reflection.
To do this without Reflection (which can be too slow for some scenarios), you can do something like this:
public static List<T> GetDistinct<T>( IEnumerable<Fruits> fruitsList) where T : IFruit
{
var ft = typeof(T);
Func<Fruits, List<T>> picker;
if (ft == typeof(Apple))
{
picker = (fruits) => (List<T>)(object)fruits.Apples;
}
else if (ft == typeof(Mango))
{
picker = (fruits) => (List<T>)(object)fruits.Mangos;
}
else
{
throw new NotImplementedException($"Fruit Type {ft.Name} not supported");
}
var rv = new Dictionary<long, T>();
foreach (var t in fruitsList.SelectMany(picker))
{
if (!rv.ContainsKey(t.Id))
{
rv.Add(t.Id, t);
}
}
return rv.Values.ToList();
}

How to set values of object array [duplicate]

This question already has answers here:
Elegant initialization of an array of class instances in C# [closed]
(3 answers)
Constructor for an array of class objects
(2 answers)
Closed 1 year ago.
Hi I have this code not sure how I can set the value of Value and Value1
public class testclass {
public ID[] test { get; set; }
public class ID
{
[JsonPropertyName("ID")]
public string Value { get; set; }
public string Value1 { get; set; }
}
}
e.g. var a = new testclass ();
a.test = ????
The fastest way with your existing code is:
a.test = new testclass.ID[] { new testclass.ID() { Value = "test", Value1 = "test1" } };
But some refactoring might help you a bit. Here's a fully compiling example.
Constructors were added to make the syntax cleaner. Rather than using the syntax of new ID { Value = "", Value1 = "" }; you can use new ID("", "");. Note that since you're doing serialization/deserialization, you may need to explicitly include a parameterless constructor, as it's unclear from your small code sample how this might get handled.
And the ID class was separated out, no longer 'underneath' the testclass class.
using System.Text.Json.Serialization; // from System.Text.Json library
namespace SomeNamespace
{
public class Program
{
static void Main()
{
var id = new ID("hello", "world");
var a = new testclass(id);
}
}
public class testclass
{
public ID[] test { get; set; }
public testclass() { /* might need parameterless for serialization */ }
// just makes an array with one entry
public testclass(ID id)
{
test = new ID[] { id };
}
}
// separate ID class from 'testclass'
public class ID
{
[JsonPropertyName("ID")]
public string Value { get; set; }
public string Value1 { get; set; }
public ID() { /* might need parameterless for serialization */ }
public ID(string value, string value1)
{
Value = value;
Value1 = value1;
}
}
}
This is what you're looking for:
var a = new testclass ();
a.test = new testclass.ID[]{};
You can also use object initialization like this:
a.test = new testclass.ID[]{
new testclass.ID(){Value = "1", Value1 = "2"},
new testclass.ID(){Value = "AnotherValue", Value1 = "10"}
};
And to read individual values:
a.test[0].Value == "1"
a.test[1].Value1 == "10"
Though these kind of nested classes are not recommended for most cases, it should work.

Json to C# object handling dynamic properties

I am trying to implement the json structure in c# objects and I am trying to understand how I can use the correct object depending on the type. For example:
public class RootObject
{
public string name { get; set; }
public Content content { get; set; }
}
public class Content
{
public string id{ get; set; }
public string type { get; set; }
public Dictionary<string, Item> child { get; set; }
}
public class Item
{
public string id { get; set; }
public string type { get; set; }
public List<string> model { get; set;}
public string[] color {get; set;}
}
Please note this is just an example there are more properties for each object. If Json contains type = "Boy" how can I generate the boy object.
Example JSON:
string json = #"
{
'name': 'Object 1',
'content': {
'body': {
'id': 'body',
'type': 'Body'
},
'style': {
'id': 'style',
'type': 'Style'
},
'DynamicName-123': {
'id': 'DynamicName-123',
'type': 'Row'
'model': {},
'colors': []
},
'DynamicName-434': {
'id': 'DynamicName-434',
'type': 'Column'
'model': {},
'colors': []
},
'DynamicName-223': {
'id': 'DynamicName-223',
'type': 'Item'
'model': {},
'colors': []
}
}
}";
If your key/value pair are not fixed and data must be configurable then Newtonsoft.json has one feature that to be use here and that is [JsonExtensionData] Read more
Extension data is now written when an object is serialized. Reading and writing extension data makes it possible to automatically round-trip all JSON without adding every property to the .NET type you’re deserializing to. Only declare the properties you’re interested in and let extension data do the rest.
In your case, suppose there is a class,
public class MyClass
{
public string Qaz { get; set; }
public string Wsx { get; set; }
[JsonExtensionData]
public Dictionary<string, JToken> child { get; set; }
public MyClass()
{
child = new Dictionary<string, JToken>();
}
}
In the above class, you know that Qaz and Wsx are always present from your json either they contain value or null,
But for dynamic data, you can't say which key/value pair you will receive from your json so the [JsonExtensionData] can collect all those key/value pair in a dictionary.
Suppose the below classes will be for your dynamic data,
public class ABC
{
public string Abc { get; set; }
}
public class PQR
{
public string Pqr { get; set; }
}
public class XYZ
{
public string Xyz { get; set; }
}
Serialization:
ABC aBC = new ABC { Abc = "abc" };
PQR pQR = new PQR { Pqr = "pqr" };
XYZ xYZ = new XYZ { Xyz = "xyz" };
MyClass myClass = new MyClass();
myClass.Qaz = "qaz";
myClass.Wsx = "wsx";
myClass.child.Add("ABC", JToken.FromObject(aBC));
myClass.child.Add("PQR", JToken.FromObject(pQR));
myClass.child.Add("XYZ", JToken.FromObject(xYZ));
string outputJson = JsonConvert.SerializeObject(myClass);
This will give you json like
{
"Qaz": "qaz",
"Wsx": "wsx",
"ABC": {
"Abc": "abc"
},
"PQR": {
"Pqr": "pqr"
},
"XYZ": {
"Xyz": "xyz"
}
}
Deserialization:
MyClass myClass = JsonConvert.DeserializeObject<MyClass>(outputJson);
string Qaz = myClass.Qaz;
string Wsx = myClass.Wsx;
if (myClass.child.ContainsKey("ABC"))
{
ABC abcObj = myClass.child["ABC"].ToObject<ABC>();
}
if (myClass.child.ContainsKey("PQR"))
{
PQR pqrObj = myClass.child["PQR"].ToObject<PQR>();
}
if (myClass.child.ContainsKey("XYZ"))
{
XYZ pqrObj = myClass.child["XYZ"].ToObject<XYZ>();
}
Conclusion: The main aim of [JsonExtensionData] is to keep your json class hierarchy simple and more readable so you don't need to manage class structure for every property.
Get all dynamic data with the specific key in JToken inside Dictionary :
You can use LINQ to fetch all dynamic data of particular key from the above dictionary.
var allAbcTypes = myClass.child
.SelectMany(x => x.Value
.ToObject<JObject>()
.Properties()
.Where(p => p.Name == "Abc") //<= Use "Column" instead of "Abc"
.Select(o => new ABC //<= Use your type that contais "Column" as a property
{
Abc = o.Value.ToString()
})).ToList();
In your case, Its something like,
var allColumnTypes = myClass.child
.SelectMany(x => x.Value
.ToObject<JObject>()
.Properties()
.Where(p => p.Name == "Column")
.Select(o => new Item
{
id = x.Value["id "].ToString(),
type = x.Value["type "].ToString(),
model = x.Value["model"].ToObject<List<string>>(),
color = x.Value["color"].ToObject<string[]>()
})).ToList();
If you want to deserialize to a dictionary with a Key string and a dynamic value (boy or girl in this case), the only way I Know is using Dynamic class:
public List<Dictionary<string, dynamic>> child { get; set; }

generate all possible combinations for a dynamic list of attributes with their values

I struggle with generating all possible combinations for a List of Attributes with their possible values. What I would like to implement is a Method like this:
public List<Variant> generateAllPossibleVariants(List<Attribute> attributes)
The Attribute Class looks the following:
public class Attribute {
public String Name { get; set; }
public ICollection<String> PossibleValues { get; protected set; }
}
So imagine you have a list of 2 Attributes (while the count is dynamic) with their possible values:
attributeColor with possible Values of ( "red", "blue" )
attributeSize with possible values of ("XL", "L" )
Now my method should return a List of Variant while the Variant Class looks the following:
public class Variant
{
public IDictionary<Attribute, string> AttributeValues { get; private set; }
}
Now my method should return a List of all combinations like the following:
List<Variant> :
Variant.AttributeValues { attributeColor => "red", attributeSize => "XL" }
Variant.AttributeValues { attributeColor => "red", attributeSize => "L" }
Variant.AttributeValues { attributeColor => "blue", attributeSize => "XL" }
Variant.AttributeValues { attributeColor => "blue", attributeSize => "L" }
This is not an optimized code, but you can get the idea and clean it up yourself:
public void Main()
{
var attr1 = new MyAttribute { Name = "Colors", PossibleValues = new List<string> { "red", "blue" } };
var attr2 = new MyAttribute { Name = "Sizes", PossibleValues = new List<string> { "XL", "L" } };
var attr3 = new MyAttribute { Name = "Shapes", PossibleValues = new List<string> { "qube", "circle" } };
var attrList = new List<MyAttribute> { attr1, attr2, attr3 };
var result = attrList.Skip(1).Aggregate<MyAttribute, List<Variant>>(
new List<Variant>(attrList[0].PossibleValues.Select(s => new Variant { AttributeValues = new Dictionary<MyAttribute, string> { {attrList[0], s} } })),
(acc, atr) =>
{
var aggregateResult = new List<Variant>();
foreach (var createdVariant in acc)
{
foreach (var possibleValue in atr.PossibleValues)
{
var newVariant = new Variant { AttributeValues = new Dictionary<MyAttribute, string>(createdVariant.AttributeValues) };
newVariant.AttributeValues[atr] = possibleValue;
aggregateResult.Add(newVariant);
}
}
return aggregateResult;
});
}
public class MyAttribute
{
public string Name { get; set; }
public ICollection<string> PossibleValues { get; set; }
}
public class Variant
{
public IDictionary<MyAttribute, string> AttributeValues { get; set; }
}
You are looking for cartesian product (with dynamic dimension).
One simple way to achieve it is using recursion on the dimension, and each time invoke cartesian product on the result of the recursion, and one of the dimensions.
Pseudo code:
genAllPossibilities(list attributes) //each element in attributes is a list
if length(attributes) == 1:
return attributes[0] //the only element, which is a list of one attribute
else:
curr = head(attributes) // first element in the list
reminder = tails(attributes) // a list of all elements except the first
return cartesianProduct(genAllPossibilities(reminder), curr)
cartesianProduct(list1, list2):
l = new list
for each x1 in list1:
for each x2 in list2:
l.append(new MyObject(x1,x2))
return l

Using contravariance with Func<T, object> selector property

I am designing a generic column definitions class which will act as a selector of properties from entities, all this to make it easier to manage grid presentations of different aspects in a LOB application.
Unfortunately I hit a wall trying to use generic parameter in a class which will be contained in a collection. Example implementation for SettingsContext class below explains what is happening:
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T>: IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public class ColumnSet
{
public Type TypeHandled { get; set; }
public IEnumerable<IDisplayColumn<object>> Columns { get; set; }
}
public static class ColumnSetTest
{
static ColumnSetTest()
{
// Cannot implicitly convert type 'DisplayColumn<System.Configuration.SettingsContext>' to 'IDisplayColumn<object>'.
// An explicit conversion exists (are you missing a cast?)
IDisplayColumn<object> testSingleColumn = new DisplayColumn<SettingsContext> {Title = "Test", Selector = x => x.Values };
// another test with other type used as a source which should be assignable to DisplayColumn<object>
testSingleColumn = new DisplayColumn<SettingsProvider> { Title="Another test", Selector = x => x.ApplicationName };
// Cannot implicitly convert type 'System.Collections.Generic.List<IDisplayColumn<System.Configuration.SettingsContext>>'
// to 'System.Collections.Generic.IEnumerable<IDisplayColumn<object>>'.
// An explicit conversion exists (are you missing a cast?)
var columnSets = new List<ColumnSet>
{
new ColumnSet
{
TypeHandled = typeof(SettingsContext),
Columns = new List<IDisplayColumn<SettingsContext /* or object */>>
{
new DisplayColumn<SettingsContext> {Title = "Column 1", Order = 1, Selector = x => x.IsReadOnly },
new DisplayColumn<SettingsContext> {Title = "Column 2", Order = 2, Selector = x => x.IsSynchronized },
new DisplayColumn<SettingsContext> {Title = "Column 3", Order = 3, Selector = x => x.Keys }
}
}
};
}
}
How I understand the purpose of covariance and contravariance this is really expected - out parameter should be used for IDisplayColumn testSingleColumn = new DisplayColumn assignment but I need to make Func in parameter generic, out will always be an object.
How to implement such scenario, would it require implementing custom Func or maybe dotnet has already a type suited for such purpose?
Currently the only solution I can see is to create non-generic DisplayColumn class with Func< object, object > Selector property and casting argument to a concrete type in each assignment which is obviously not a great solution. Another option would be to inherit base non-generic DisplayColumn class and put generic selector in inherited generic class but then using this expression when presenting data would require invoking generic method in inherited generic class which is really unacceptable by performance and code quality standards.
If you make your ColumnSet generic as well, then you can specify the type used for the columns enumerable that it returns. The code below will compile, and I think achieve what you are after.
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T>: IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public class ColumnSet<T>
{
public Type TypeHandled { get; set; }
public IEnumerable<IDisplayColumn<T>> Columns { get; set; }
}
public static class ColumnSetTest
{
static ColumnSetTest()
{
IDisplayColumn<SettingsContext> testSingleColumn = new DisplayColumn<SettingsContext> { Title = "Test", Selector = x => x.Values };
var columnSets = new List<ColumnSet<SettingsContext>>
{
new ColumnSet<SettingsContext>
{
TypeHandled = typeof(SettingsContext),
Columns = new List<IDisplayColumn<SettingsContext>>
{
new DisplayColumn<SettingsContext> {Title = "Column 1", Order = 1, Selector = x => x.IsReadOnly },
new DisplayColumn<SettingsContext> {Title = "Column 2", Order = 2, Selector = x => x.IsSynchronized },
new DisplayColumn<SettingsContext> {Title = "Column 3", Order = 3, Selector = x => x.Keys }
}
}
};
}
}
After thorough investigation I found out the solution would require mixing covariance and contravariance which is not supported currently. The closest solution (which compiles) actually does not allow easy access to IDisplayColumn.Selector as T argument in IColumnSet.Columns will be visible as object not IDisplayColumn so it's not an option:
public interface IDisplayColumn<in T>
{
string Title { get; set; }
int Order { get; set; }
Func<T, object> Selector { get; }
}
public class DisplayColumn<T> : IDisplayColumn<T>
{
public string Title { get; set; }
public int Order { get; set; }
public Func<T, object> Selector { get; set; }
}
public interface IColumnSet<out T>
{
Type TypeHandled { get; }
IEnumerable<T> Columns { get; }
}
public class ColumnSet<T> : IColumnSet<IDisplayColumn<T>>
{
public Type TypeHandled
{
get
{
return typeof(T);
}
}
public IEnumerable<IDisplayColumn<T>> Columns { get; set; }
}
I ended up translating Func<,> using expressions when creating which is a one-time operation with minimal overhead of casting when using selector:
public interface IDisplayColumn
{
string Title { get; set; }
bool Visible { get; set; }
int Order { get; set; }
Func<object, object> Value { get; }
T GetValue<T>(object source);
}
public class DisplayColumn<T>: IDisplayColumn
{
public string Title { get; set; }
public bool Visible { get; set; }
public int Order { get; set; }
public Func<object, object> Value { get; set; }
public override string ToString()
{
return Title;
}
public TValue GetValue<TValue>(object source)
{
return (TValue)Convert.ChangeType(Value(source), typeof(TValue));
}
public Func<T, object> Selector
{
set
{
Value = value.ConvertObject<T>();
}
}
}
public interface IColumnSet
{
Type TypeHandled { get; }
IEnumerable<IDisplayColumn> Columns { get; }
}
public class ColumnSet<T>: IColumnSet
{
public Type TypeHandled
{
get
{
return typeof(T);
}
}
public IEnumerable<IDisplayColumn> Columns { get; set; }
}
public static Func<object, object> ConvertObject<T>(this Func<T, object> func)
{
Contract.Requires(func != null);
var param = Expression.Parameter(typeof(object));
var convertedParam = new Expression[] { Expression.Convert(param, typeof(T)) };
Expression call;
call = Expression.Convert(
func.Target == null
? Expression.Call(func.Method, convertedParam)
: Expression.Call(Expression.Constant(func.Target), func.Method, convertedParam)
, typeof(object));
var delegateType = typeof(Func<,>).MakeGenericType(typeof(object), typeof(object));
return (Func<object, object>)Expression.Lambda(delegateType, call, param).Compile();
}
And the example of usage:
private class TestObject1
{
public int Id { get; set; }
public string Name { get; set; }
}
IDisplayColumn objectColumn = new DisplayColumn<TestObject1> { Title = "Column 1", Selector = (x) => x.Name };
var columnSets = new List<IColumnSet>
{
new ColumnSet<TestObject1>
{
Columns = new List<IDisplayColumn>
{
new DisplayColumn<TestObject1> { Title = "Column 1", Order = 3, Selector = x => x.Id },
new DisplayColumn<TestObject1> { Title = "Column 2", Order = 2, Selector = x => x.Name },
new DisplayColumn<TestObject1> { Title = "Column 3", Order = 1, Selector = x => x.Id.ToString(CultureInfo.InvariantCulture) + x.Name.ValueOrEmpty() },
}
}
};
So I will give myself the credit for this problem but if somebody can suggest a nicer solution using generics and variance, please feel free to post it as I will be happy to change the solution.

Categories

Resources