C# How to cast List<object[]> into List<customClass> - c#

Here is my code .Can be run in Linqpad.
void Main(){
List<Object> listobj=new List<object>{
new object[]{"A01001","sucess","on"},
new object[]{"A01002","fail","off"}};
listobj.Dump();
var second = listobj.Cast<RowItem>();
second.Dump();
}
public class RowItem {
public string GOODS_ID { get; set; }
public string AUDIT_STATUS { get; set; }
public string APPLY_STATUS { get; set; }
}
I want convert List<object> to List<RowItem>, but when I am using the cast method, it returns an error cannot convert type 'System.Object[]' to class RowItem
Is this possible, or is there another way of accomplishing this?
Thank you.

Your listobj's type is incorrect at many levels. The type is a collection of object arrays concealed as object array. If you want to continue with the same type, here is the code that will work.
void Main()
{
List<Object> listobj = new List<object>{
new object[]{"A01001","sucess","on"},
new object[]{"A01002","fail","off"}};
listobj.Dump();
var second = listobj.Cast<object[]>().Select(l => new RowItem {
GOODS_ID=l[0].ToString(),
AUDIT_STATUS=l[1].ToString(),
APPLY_STATUS=l[2].ToString()
});
second.Dump();
}
public class RowItem
{
public string GOODS_ID { get; set; }
public string AUDIT_STATUS { get; set; }
public string APPLY_STATUS { get; set; }
}

Related

How do I send a Object Linq sorted List as a parameter

I am trying to make my code more compromised, and use overall less, however currently I'm running into the problem of not being able to send a list of Objects sorted by linq as a parameter.
the problem is in this part of the code:
List<Afspraken> dataAfspraken = new List<Afspraken>();
public Form1()
{
InitializeComponent();
fillListsForLinq();
loadReceptionData();
}
private void fillListsForLinq()
{
dataAfspraken = data.getAfsprakenData();
//here it fills the list with Afspraken objects
}
private void loadReceptionData()
{
private void loadReceptionGrid
var receptionToFinnish =
(from AFspraken in dataAfspraken
where Afspraken.factuur_betaald == true && Afspraken.volledig_afgerond == false
join Users in dataUsers on Afspraken.gekoppelde_klant equals Users.id
select new
{
Id = Afspraken.id,
Klant = Users.gebruikersnaam,
Betaald = Afspraken.factuur_betaald,
Afgerond = Afspraken.volledig_afgerond
}).ToList();
changeDataviewReception(receptionToFinnish);
}
private void changeDataviewReception(List<Object> listData)
{
dgvReceptionData.DataSource = listData
}
the Afspraken class looks like this
public class Afspraken
{
public int id { get; set; }
public bool bevestigd { get; set; }
public DateTime datum { get; set; }
public int gekoppelde_klant { get; set; }
public int gekoppelde_monteur { get; set; }
public string benodigde_hadelingen { get; set; }
public decimal totaalprijs { get; set; }
public bool klaar { get; set; }
public bool factuur_betaald { get; set; }
public bool volledig_afgerond { get; set; }
public string opmerkingen { get; set; }
}
How do I get receptionToFinnish as a parameter into changeDataviewReception?
receptionToFinnish will be a list full of objects of an anonymous type. But your method requires a List<object>. This is now allowed since a list is not a variant type.
Say for example that you have a list of bananas and want to give it to someone that wants a list of fruits. This will not work since that other person might try to add an orange to the list of bananas.
To fix this, cast the values to object explicitly, for example:
select new
{
Id = Afspraken.id,
Klant = Users.gebruikersnaam,
Betaald = Afspraken.factuur_betaald,
Afgerond = Afspraken.volledig_afgerond
} as object

AutoMapper, Mapping a nested collection of collections to List

I have just started using AutoMapper on an asp net core project and I'm trying to map an object that has a collection of an object that also has a collection of an object to an entity.
The source
public class MyClass
{
public List<MyCollection> MyCollections { get; set; }
}
public class MyCollection
{
public int CollectionId { get; set; }
public List<Description> Descriptions { get; set; }
}
public class Description
{
public int DescriptionId { get; set; }
public string Text { get; set; }
}
The destination
public class DescriptionToCollection
{
public int DescriptionId { get; set; }
public int CollectionId { get; set; }
}
I've played around with ConvertUsing thinking something like this, but I can't make it work.
CreateMap<MyClass, List<DescriptionToCollection>>()
.ConvertUsing(source => source.MyCollections.Select(x =>x.Description.Select(y=> new DescriptionToCollection{ DescriptionId=y.DescriptionId,CollectionId=x.CollectionId}).ToList()
));
Searching AutoMappers docs and the internet, I couldn't find anything similar to my problem.
Any help is highly appreciated.
Besides a typo in your example code, you almost had it. Because you aren't mapping 1:1 at the top level, you need to flatten somewhere, and you do that using SelectMany, moving the ToList call appropriately.
CreateMap<MyClass, List<DescriptionToCollection>>()
.ConvertUsing(source => source.MyCollections.SelectMany(x => // SelectMany to flatten
x.Descriptions.Select(y =>
new DescriptionToCollection
{
DescriptionId = y.DescriptionId,
CollectionId = x.CollectionId
}
) // ToList used to be here
).ToList()
);
Try to implement ITypeConverter, follow the example code:
Your Classes
public class Class1
{
public List<Class2> class2 { get; set; }
}
public class Class2
{
public int CollectionId { get; set; }
public List<Class3> class3 { get; set; }
}
public class Class3
{
public int DescriptionId { get; set; }
public string Text { get; set; }
}
public class ClassDto
{
public int DescriptionId { get; set; }
public int CollectionId { get; set; }
}
The custom map
public class ClassCustomMap : ITypeConverter<Class1, List<ClassDto>>
{
public List<ClassDto> Convert(Class1 source, List<ClassDto> destination, ResolutionContext context)
{
var classDtoList = new List<ClassDto>();
foreach (var item in source.class2)
{
var collectionID = item.CollectionId;
foreach (var obj in item.class3)
{
var classDto = new ClassDto();
classDto.CollectionId = collectionID;
classDto.DescriptionId = obj.DescriptionId;
classDtoList.Add(classDto);
}
}
return classDtoList;
}
}
The mapping declaration
CreateMap<Class1, List<ClassDto>>().ConvertUsing<ClassCustomMap>();
How to use it
var class2 = new Class2();
class2.CollectionId = 2;
var class3 = new Class3();
class3.DescriptionId = 1;
class3.Text = "test";
class2.class3 = new System.Collections.Generic.List<Class3>() { class3 };
var class1 = new Class1();
class1.class2 = new System.Collections.Generic.List<Class2>() { class2 };
var result = mapper.Map<List<ClassDto>>(class1);
For clarity and to simplify I have used explicit cycles, if you want you can optimize the conversion function using LinQ and Lambda
You are missing the purpose of auto-mapper.
It should be used for transforming an input object of one type into an output object of a different type.
And you wanted to create a map from MyClass type to List - this should be treated as projection.
You can achieve that using LINQ (for example as a extension method on MyClass):
public static class MyClassExtension
{
public static List<DescriptionToCollection> ToDescriptionToCollection(this MyClass value)
{
return value.MyCollections.SelectMany(mc => mc.Descriptions.Select(d => new DescriptionToCollection()
{
CollectionId = mc.CollectionId,
DescriptionId = d.DescriptionId
})).ToList();
}
}

unable to get list of elements in list

i have 2 model classes
public class ProductOptionRequest
{
public string Name { set; get; }
public List<ProductValuesRequest> productValues { get; set; }
}
public class ProductValuesRequest
{
public string ValueName { get; set; }
}
public class ProductOptionValue
{
public int OptionId { get; set; }
public String ValueName { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
and wrote one bs method and passing parameter value as value names. but I'm unable to get those values in a list object as productValues. May I know the solution, please.
public async Task<ReturnString> SaveProductOption(ProductOptionRequest request)
{
request.productValues = new List<ProductValuesRequest>();
foreach (ProductValuesRequest valueRequest in request.productValues)
{
ProductOptionValue res = new ProductOptionValue();
res.ValueName = valueRequest.ValueName;
object response = await productOptionValueRepository.InsertAsync(res, true);
}
}
In the first line of your method, you are replacing the productValues property of request object with a new empty list, :
request.productValues = new List<ProductValuesRequest>();
Therefore, in foreach loop, you are iterating on an empty list.
Remove the first line and see if you still have any issues.
You are assigning an emplty list to productValues as
request.productValues = new List() and trying to iterate the empty list.

Loop trought Dictionary<string, object> only for a key in c#

I have a dictionary of strings and object that i obtained deserializing this json answer:
{"labels":[{"id":"1","descrizione":"Etichetta interna","tipo":"0","template_file":"et_int.txt"},{"id":"2","descrizione":"Etichetta esterna","tipo":"1","template_file":"et_ext.txt"}],"0":200,"error":false,"status":200}
using the code:
var labels = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Now i want to loop only trought the objects inside the "labels" key.
I tried
foreach (var outer in labels["labels"]){/* code */}
but i got error:
CS1579: foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public definition for 'GetEnumerator'.
Solved replacing the dictionary with a class, thank you
Create a class to deserialize your json:
To create classes, you can copy the json in clipboard and use the
Edit / Paste special / Paste JSON as class
in visual studio (I use vs2013).
[TestMethod]
public void test()
{
string json = "{\"labels\" : [{\"id\" : \"1\",\"descrizione\" : \"Etichetta interna\",\"tipo\" : \"0\",\"template_file\" : \"et_int.txt\"}, {\"id\" : \"2\",\"descrizione\" : \"Etichetta esterna\",\"tipo\" : \"1\",\"template_file\" : \"et_ext.txt\"}],\"0\" : 200,\"error\" : false,\"status\" : 200}";
var root = JsonConvert.DeserializeObject<Rootobject>(json);
foreach (var label in root.Labels)
{
//Use label.Id, label.Descrizione, label.Tipo, label.TemplateFile
}
}
public class Rootobject
{
public Label[] Labels { get; set; }
public int _0 { get; set; }
public bool Error { get; set; }
public int Status { get; set; }
}
public class Label
{
public string Id { get; set; }
public string Descrizione { get; set; }
public string Tipo { get; set; }
public string TemplateFile { get; set; }
}
You need to loop through your dictionary.
foreach(KeyValuePair<string, Object> entry in labels)
{
// do something with entry.Value or entry.Key
}
Once you start looping through it you will get access to key and value. Since you are interested to look at entry.value you can do operation on that easily. Currently your dictionary value is type of object which does not have an enumerator
Your problem is that you've defined the Type of Value for each dictionary entry as object. C# can't know how to loop over on object. So you need to work out what type is actually inside the object once the JavaScriptSerializer have parsed the JSON. One way is
var t = typeof(labels["labels"]);
Once you know what type the serializer is creating, all you need to do is cast the object back to that type. For example, assuming it's a list of objects
var labels = (List<object>)labels["labels"];
foreach (var label in labels)
{
}
Alternatively, if each object in the JSON is the same, you could try create the dictionary as the type you need. So you serializing becomes
var labels = new JavaScriptSerializer()
.Deserialize<Dictionary<string, List<object>>>(json);
A possible solution:
static void Main(string[] args) {
string json = #"{'labels':[{'id':'1','descrizione':'Etichetta interna','tipo':'0','template_file':'et_int.txt'},{'id':'2','descrizione':'Etichetta esterna','tipo':'1','template_file':'et_ext.txt'}],'0':200,'error':false,'status':200}";
var labels = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
IEnumerable inner_labels = labels["labels"] as IEnumerable;
if (inner_labels != null) {
foreach (var outer in inner_labels) {
Console.WriteLine(outer);
}
}
}
Otherwise, you can create a class with deserialization information and instruct the deserializer to deserialize your json string to that type:
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
[Serializable]
public class JsonData {
[XmlElement("labels")]
public List<JsonLabel> labels { get; set; }
[XmlElement("0")]
public int zero { get; set; }
[XmlElement("error")]
public bool error { get; set; }
[XmlElement("status")]
public int status { get; set; }
}
[Serializable]
public class JsonLabel {
[XmlElement("id")]
public int id { get; set; }
[XmlElement("descrizione")]
public string descrizione { get; set; }
[XmlElement("tipo")]
public int tipo { get; set; }
[XmlElement("template_file")]
public string template_file { get; set; }
}
class Program {
static void Main(string[] args) {
string json = #"your json string here...";
var jsonData = new JavaScriptSerializer().Deserialize<JsonData>(json);
foreach (var label in jsonData.labels) {
Console.WriteLine(label.id);
}
}
}
Could you please try below snippet?
It might be help you.
foreach (var item in labels["labels"] as ArrayList)
{
Console.Write(item);
}

How do i cast a list<x> to List<y>

i have two classes as below i need to cast list<child> to list<BM>
public class Child
{
[JsonProperty("name")]
public string title { get; set; }
public string type { get; set; }
public string url { get; set; }
public List<Child> children { get; set; }
}
public class BM
{
public string title { get; set; }
public string type { get; set; }
public string url { get; set; }
public List<BM> children { get; set; }
}
You can't cast it. You can create new list with all items transformed from one class to another, but you can't cast the entire list at once.
You should probably create a method which will transform Child into BM instance:
public static BM ToBM(Child source)
{
return new BN() {
title = source.title,
type = source.type,
url = source.url,
children = source.children.Select(x => ToBM(x)).ToList()
};
}
and then use LINQ to transform entire list:
var BMs = source.Select(x => ToBM(x)).ToList();
use automapper's DLL. You can read more about automapper at http://automapper.codeplex.com/wikipage?title=Lists%20and%20Arrays
List<BM> BMList=
Mapper.Map<List<Child>, List<BM>>(childList);
same question has been asked before
Automapper copy List to List
You can also use Custom Type Conversions if you want to cast between custom types like that:
Class2 class2Instance = (Class2)class1Instance;
So all you need is to define explicit or implicit conversion function in your child class.
// Add it into your Child class
public static explicit operator BM(Child obj)
{
BM output = new BM()
{
title = obj.title,
type = obj.type,
url = obj.url,
children = obj.children.Select(x => BM(x)).ToList()
};
return output;
}
and then:
var result = source.Select(x => (BM)x).ToList();

Categories

Resources