how to convert dynamic variable to specific class.
dynamic variable has the same properties as my specific class.
public class PracovnikHmotZodpovednostDropDownListItem
{
[Column("ZAZNAM_ID")]
public int? ZaznamId { get; set; }
[Column("TEXT")]
public string Text { get; set; }
[Column("VALL")]
public int Value { get; set; }
public bool Disabled { get; set; } = false;
public UpdateStatusEnum UpdateStatus { get; set; }
}
void someMethod(dynamic dtos){
List<PracovnikHmotZodpovednostDropDownListItem> dto =
(List<PracovnikHmotZodpovednostDropDownListItem>)dtos;
}
If all you know is that the properties have the same names, you're in duck typing territory, casting won't help you.
Good news is, it's trivial to do, just tedious:
var dtoList = new List<PracovnikHmotZodpovednostDropDownListItem>();
foreach(var dto in dtos)
dtoList.Add(new()
{
ZaznamId = dto.ZaznamId,
Text = dto.Text,
// etc..
});
Related
I have the following class which is populated after de-serializing a JSON string:
public class Doors
{
public List<Door> doors { get; set; }
}
public class Door
{
public int id { get; set; }
public string name { get; set; }
public bool elevator { get; set; }
}
JSON string:
var result = JsonConvert.DeserializeObject<Doors>(response.Content);
// "{\"doors\":[{\"id\":1,\"name\":\"Main Door\",\"elevator\":false},{\"id\":2,\"name\":\"Back Door\",\"elevator\":false}]}"
The data maps to my class fine, I'm then trying to pass the class data to another class:
public class WS4APIResult
{
public List<Door> doors { get; set; } = new List<Door>();
}
public class Door
{
public int id { get; set; }
public string name { get; set; }
public bool elevator { get; set; }
}
return new WS4APIResult() {
doors = result.doors
}
With the following error: any ideas please?
Cannot implicitly convert type 'System.Collections.Generic.List<WS4PortalApi.Models.Door>' to 'System.Collections.Generic.List<WS4PortalApi.Domain.Door>'
The two c#-Files refer to different classes if you type Door. You need to implement a conversion between WS4PortalApi.Models.Door and WS4PortalApi.Domain.Door.
Like:
public static WS4PortalApi.Domain.Door DoorConvert(WS4PortalApi.Models.Door door)
then you can use linq to generate a new List
doors = result.doors
.Select(d => DoorConvert(d))
.ToList();
You have to map the properties of your domain object to those of the model.
I normally create a method for this like:
var doors = new List<Model.Door>();
foreach(door in result.doors)
{
var doorModel = new Model.Door
{
id = door.id,
name = door.name,
elevator = door.elevator
};
doors.Add(doorModel);
}
return doors;
Or you can use a library like automapper.
I reposted question on codereview but can not delete this question couse already answer here.
I have some classes:
public abstract class House
{
public string Name { set; get;}
public SomeClass Property1 { set; get;}
public OtherClass Property2 { set; get;}
}
public class WoodenHouse:House
{
public string WoodType { set; get;}
public int WoodAge { set; get;}
}
public class StoneHouse:House
{
public string StoneType { set; get;}
}
And trying to create Factory Method pattern for this:
abstract class Creator
{
public abstract HouseInfo Info { get; set; }
public Creator()
{
}
public abstract House FactoryMethod();
}
class WoodenHouseCreator : Creator
{
public override HouseInfo Info { get; set; }
public WoodenHouseCreator(WoodenHouseInfo info)
{
Info = info;
}
public override House FactoryMethod()
{
var info = Info as WoodenHouseInfo;
var woodenHouse = new WoodenHouse();
woodenHouse.Name = info.Name;
woodenHouse.Floors = info.Floors;
woodenHouse.RoofType = info.RoofType;
woodenHouse.WoodType = info.WoodType;
woodenHouse.WoodAge = info.WoodAge;
return woodenHouse;
}
}
class StoneHouseCreator : Creator
{
public override HouseInfo Info { get; set; }
public StoneHouseCreator(StoneHouseInfo info)
{
Info = info;
}
public override House FactoryMethod()
{
var info = Info as StoneHouseInfo;
var stoneHouse = new StoneHouse();
stoneHouse.Name = info.Name;
stoneHouse.Floors = info.Floors;
stoneHouse.RoofType = info.RoofType;
stoneHouse.StoneType = info.StoneType;
return stoneHouse;
}
}
Here are the classes what contain information to create ahouse:
class HouseInfo
{
public string Name { set; get; }
public int Floors { set; get; }
public string RoofType { set; get; }
}
class WoodenHouseInfo : HouseInfo
{
public string WoodType { set; get; }
public int WoodAge { set; get; }
}
class StoneHouseInfo : HouseInfo
{
public string StoneType { set; get; }
}
And Usage:
var houseInfo = new WoodenHouseInfo
{
Name = "HouseName",
Floors = 2,
RoofType = "Triangle",
WoodType = "Pine",
WoodAge = 100
};
House house;
if(houseInfo is WoodenHouseInfo)
{
var creator = new WoodenHouseCreator(houseInfo);
house = creator.FactoryMethod();
Console.Write((house as WoodenHouse).WoodAge);
}
Full code fiddle.
My problem is how to handle code duplication. I mean there is a lot of lines that fills base House object properties. How can I write that code only once?
Or I should not to use Factory Method?
Currently your factories instantiate the new objects and then fill in all of their properties with the right values. You could split instantiation from property value assignment. Your StoneHouseCreator could instantiate a StoneHouse, use a HousePopulator that populates the values that all objects of type House have in common, and then the StoneHouseCreator could populate the rest of the values that are exclusive to a StoneHouse. That same HousePopulator could also be used by your WoodenHouseCreator, which would then proceed to populate the WoodenHouse-specific properties.
If you want to philosophise about this at a higher level, these are the problems that we run into because of inheritance. Factories, that is the logical separation of object use from object creation, are more naturally suited to cases where you use composition over inheritance. If you are interested more in this, I would recommend reading this excellent article on the topic.
I am new to c# and .NET. I am learning ASP.NET MVC 5. One thing that I am finding myself spending extra time doing in converting a model to a viewmodel.
Here is my model
public class Overview
{
public string chain_name { get; set; }
public int store_id { get; set; }
public int total_attempts { get; set; }
public int total_unique_number_called { get; set; }
public int total_callable { get; set; }
public int total_completed_interviews { get; set; }
}
and here is my view model
public class OverviewViewModel
{
public string chain_name { get; set; }
public int store_id { get; set; }
public int total_attempts { get; set; }
public int total_unique_number_called { get; set; }
public int total_callable { get; set; }
public int total_completed_interviews { get; set; }
public decimal? unique_number_per_complete { get; set; }
public OverviewViewModel()
{
unique_number_per_complete = 0;
}
}
as you can see both Model and ViewModel are identical except for over variable which is a calculation.
To populate my view model I do the following
var records = conn.Database.SqlQuery<Overview>(query).ToList();
var overView = new List<OverviewViewModel>();
foreach(var record in records){
var newRecord = new OverviewViewModel();
newRecord.store_id = record.store_id;
newRecord.chain_name = record.chain_name;
newRecord.total_attempts = record.total_attempts;
newRecord.total_callable = record.total_callable;
newRecord.total_completed_interviews = record.total_completed_interviews;
if (record.total_completed_interviews > 0) {
newRecord.total_unique_number_called = record.total_unique_number_called / record.total_completed_interviews;
}
overView.Add(newRecord);
}
The two issues that I am seeing with my approach is that
I have to do lots of extra coding especially of the view model is large or f I have multiple variables that I need to calculate.
I feel I am looping 1 extra time to convert my model to view mode.
Is there an easier way to do this in c#?
Is there a better approach with this procedure for a large application? My goal is to learn the better way to utilize my code time to the fullest.
I agree that you should look into automapper, but another way would be to create a constructor on your OverviewViewModel model that takes and Overview object and populates all the properties. Something like
public class OverviewViewModel {
public string chain_name { get; set; }
public int store_id { get; set; }
public int total_attempts { get; set; }
public int total_unique_number_called { get; set; }
public int total_callable { get; set; }
public int total_completed_interviews { get; set; }
public decimal? unique_number_per_complete { get; set; }
public OverviewViewModel()
{
unique_number_per_complete = 0;
}
public OverviewViewModel(Overview record)
{
store_id = record.store_id;
chain_name = record.chain_name;
total_attempts = record.total_attempts;
total_callable = record.total_callable;
//etc
}
}
Then your code would look like
var overView = new List<OverviewViewModel>();
foreach(var record in records){
overView.Add(new OverViewViewModel(record));
}
Yes, you should use Automapper, install package view Nuget. Automapper is very configurable as well.
http://automapper.org/
First, create this class:
public static class AutoMapperConfig
{
public static void RegisterMappings()
{
//Example here, creates "two way" for Overview & OverviewViewModel mapping
Mapper.CreateMap<Overview, OverviewViewModel>(); //<source, destination>
Mapper.CreateMap<OverviewViewModel, Overview>(); //<source, destination>
//..more mapping for other Models and ViewModels.
}
}
In Global.asax.ApplicationStart() add this line:
AutoMapperConfig.RegisterMappings()
Now your foreach example in your comments is nice and simple:
foreach (var record in records)
{
var newRecordOverviewViewModel = Mapper.Map<OverviewViewModel>(record); //<destination>(source)
overView.Add(newRecordOverviewViewModel);
}
Another alternative is to use Linq and extension methods as below
using System.Collections.Generic;
using System.Linq;
using App.Data.Entities;
using App.Business.Models;
namespace App.Business
{
public static partial class OverviewAdapter
{
public static OverviewViewModel ToOverviewViewModel(this Overview overview)
{
return new OverviewViewModel
{
chain_name = overview.chain_name,
store_id = overview.store_id,
total_attempts = overview.total_attempts,
total_unique_number_called = overview.total_unique_number_called,
total_callable = overview.total_callable,
total_completed_interviews = overview.total_completed_interviews,
unique_number_per_complete = 0
};
}
public static IEnumerable<OverviewViewModel> ToOverviewModelList(this IEnumerable<OverviewViewModel> overviewList)
{
return (overviewList != null) ? overviewList.Select(a => a.ToOverviewViewModel()) : new List<OverviewViewModel>();
}
// Reverse - ToOverview / ToOverviewList if needed...
}
}
Now, anytime your Business class is in scope, you have a discoverable method on the class and the list of class which can be added inline.
var records = conn.Database.SqlQuery<Overview>(query).ToOverviewModelList().ToList();
This more functional approach is intuitive, streamlined, and you have immediate feedback if an adapter has not yet been written.
It is a personal preference whether to return an IEnumerable or List from the list version. The broader IEnumerable is the more conventional solution, but I tend to be going from List<> to List<> all of the time and dropping down into IEnumerable seems superfluous.
I'm having some trouble storing and retrieving items into a list<> with a custom structure.
My structure looks like this:
public class list_rss_parameters
{
public string this_string { get; set; }
public string title_start { get; set; }
public string title_end { get; set; }
public string description_start { get; set; }
public string description_end { get; set; }
public string link_start { get; set; }
public string link_end { get; set; }
public string publish_date_start { get; set; }
public string publish_date_end { get; set; }
public string author_start { get; set; }
public string author_end { get; set; }
}
My stored procedure looks like this (and note that the variable names are the same as the custom Key names) Is this ok?
//this is the last part of a custom method that returns a list
List<list_rss_parameters> list_rss_items = new List<list_rss_parameters>();
list_rss_items.Add(new list_rss_parameters()
{
this_string = this_string,
title_start = title_start,
title_end = title_end,
description_start = description_start,
description_end = description_end,
link_start = link_start,
link_end = link_end,
publish_date_start = publish_date_start,
publish_date_end = publish_date_end,
author_start = author_start,
author_end = author_end
});
return list_rss_items;
If the above two setups are correct, how do I pull items out of the List once I return it?
List<list_rss_parameters> list_rss_parameters = new List<list_rss_parameters>();
list_rss_parameters = f_discover_rss_parameters(rss);
show(list_rss_parameters.Count.ToString());
show(list_rss_parameters[0].ToString()); //does not show this_string
show(list_rss_parameters[this_string'] //does not show this_string
show(list_rss_parameters[0][this_string'];//does not show this_string
What am I doing wrong?
You want the this_string property of the first item in your list it seems:
show(list_rss_parameters[0].this_string);
Or show all of them:
foreach(var item in list_rss_parameters)
{
Console.WriteLine(item.this_string);
}
As a side note your property names don't match the PascalCase naming convention for properties in .NET - so this_string really should be ThisString.
I have a number of classes that are all related conceptually, but some more-so at the details level than others. For example, these three classes have nearly identical properties (although member functions will vary):
public class RelatedA : IRelatedType
{
public string Name { get; set; }
public string Value { get; set; }
public DateTime Stamp { get; set; }
}
public class RelatedB : IRelatedType
{
public string Name { get; set; }
public string Value { get; set; }
public DateTime Stamp { get; set; }
}
public class RelatedC : IRelatedType
{
public string Name { get; set; }
public string Value { get; set; }
public DateTime Stamp { get; set; }
public int Special { get; set; }
}
There are a couple of other classes that are conceptually related to the above 3, but can be a bit different implementation-wise:
public class RelatedD : IRelatedType
{
public string Name { get; set; }
public string Statement { get; set; }
}
public class RelatedE : IRelatedType
{
public string Name { get; set; }
public string Statement { get; set; }
public bool IsNew { get; set; }
}
Instances of these can be created by a factory based on some sort of "type" enumerated value. The problem is that later on when these objects are being used (in a business layer, for example), there could be a lot of code like this:
IRelatedType theObject = TheFactory.CreateObject(SomeEnum.SomeValue);
if (theObject is RelatedC)
{
RelatedC cObject = theObject as RelatedC;
specialVal = cObject.Special;
}
else if (theObject is RelatedD)
{
RelatedD dObject = theObject as RelatedD;
statementVal = dObject.Statement;
}
else if (theObject is RelatedE)
{
RelatedE eObject = theObject as RelatedE;
statementVal = eObject.Statement;
isNewVal = eObject.IsNew;
}
This could be repeated in many places. Is there a better approach to the design that I should be using (there's got to be)?
You could try and factor the differences into seperate classes that are then provided so for example:
IRelatedType theObject = TheFactory.CreateObject(SomeEnum.SomeValue);
RelatedTypeHelper theHelper=TheFactory.CreateHelper(theObject);
theHelper.DoSpecialThing(theObject);
Now you won't have to have all the if else blocks, and if you add a new type which requires new handling, you just whip up a new helper implement the required pieces and you should be good to go. The helper should help document this process.
I would also question why a single method would have such a different implementation for specialVal and StatementVal could be your sample, but It makes me curious what your really doing here. can you simplify things back taking a step back and questioning the point of these being included in this specific hierarchy.