a simple question about DTO, I have a DTO class Cars, and some others subclasses of cars models inside it.
public class Cars
{
public Ferrari FerrariModel { get; set; }
public Porshe PorsheModel {get; set; }
public Mustang MustangModel { get; set; }
}
public class Ferrari
{
public string collor{ get; set; }
public int year{ get; set; }
public double price{ get; set; }
}
and Porshe and Mustang are exactly the same Ferrari. The problem is I do not know how to proceed now. I try something like that
Cars cars = new Cars();
FerrariModel fm = new FerrariModel();
cars.FerrariModel.collor = txtCollor.Text;
And it is not working, as I get the follow error in the cars.FerrariModel.collor -> "Object reference not set paragraph An Instance of hum object . the hum object declaration".
I must confess I dont even know it "is possible" or if I am "inventing prograiming", so any help woulb be greatfull.
why use only a single class? Because a need to pass a single DTO in parameters: save(Cars car); update(Cars car)
using a second separeted class would force me to "overload" the method: save(Cars car); save(Ferrari ferrari);
if I use a single class (without Ferrari, Porshe and Mustang) the program work but I have lots of variables in my InteliSense, over 50.
Thank you.
You need to assign your fm instance to your Cars.FerarriModel property.
Cars cars = new Cars();
FerrariModel fm = new FerrariModel();
cars.FerrariModel = fm;
cars.FerrariModel.collor = txtCollor.Text;
Or even just:
Cars cars = new Cars();
cars.FerrariModel = new FerrariModel() { collor = txtCollor.Text };
Related
Hey … I am facing a pratical code challenge in my project.
Let's say I have a Model class has a property called Configration. The Model object has different type of configration. For example, The Model was made of by Two Pipe objects, then one Lock object and another ten Pipe objects and they have to be in sequence.
In my project, all entity classes are derived from an Entity class that only has Name and ID property.
Model.cs
class Model{
public int ID { get; set; }
public List<ConfigrationEntry<Entity>> Config {get;set;}
}
class Pipe{
public int Length { get; set; }
}
class Lock{
public string Brand { get; set; }
}
So I create a ConfigrationEntry class that contains generic parameter.
class ConfigrationEntry<T> where T : Entity{
public int Number { get; set; }
public T Entity {get; set;}
public ConfigrationEntry(string name, int num){
Entity = new T (name);
Number = num;
}
}
However, if I want to add this ConfigrationEntry into Model.Config List. I won't allow me to do that.
class Main{
var configEntry1 = new ConfigrationEntry<Pipe>("Test1", 10);
var configEntry2 = new ConfigrationEntry<Lock>("Test2", 3);
var configEntry3 = new ConfigrationEntry<Pipe>("Test3", 3);
var Model = new Model();
// I cannot add this entry. IDE says it has to be ConfigrationEntry<Entity> type even Entity is the base class.
// model.Config.Add(configEntry1);
}
So what's the best practical solution for this scenario? Right now I am thinking two use Dictionary<string, int> and use string to find the object.
Yes you're right. You try to use covariant or contravariant (the Entity property is get; set;) and that's not working that way.
In your case you need to add an interface or base class that handles the Entity as base type and add those to the List<>.
Btw: There is a typo in ConfigrationEntry.
Change your configuration entry class to:
interface IConfigurationEntry
{
int Number { get; set; } // is set required?
Entity Entity { get; set; } // is set required?
}
class ConfigurationEntry<T> : IConfigurationEntry
where T : Entity
{
public int Number { get; set; }
public T Entity {get; set;}
Entity IConfigurationEntry.Entity
{
get => this.Entity;
set => this.Entity = (T)value;
}
public ConfigurationEntry(string name, int num){
Entity = new T (name); // this looks strange!
Number = num;
}
}
After having an interface for all ConfigurationEntry<T> instances you're able to change your model:
class Model{
public int ID { get; set; }
public List<IConfigurationEntry> Config {get;set;}
}
If you're using serialization for that Model you need to serialize any type descriptor to deserialize correct instances - but that's another topic and depends on which serialization is used.
I'm studying C# Classes and am trying to create a program that has a Class called Employee and derived classes of ProductionWorker, ShiftSupervisor, and TeamLeader.
I have a list box where I want to display All the employees, and within the program, there's functionality to add, edit, or remove respective people, but rather than making 3 lists like so:
List<ProductionWorkers> pWorkers = new List<ProductionWorkers>();
List<ShiftSupervisor> sSupervisors = new List<ShiftSupervisor>();
List<TeamLeader> tLeaders = new List<TeamLeader>();
I'd like to be able to have the Employee base class have or contain some sort of list of it's derived classes and their objects.
For example I'd like to be able to be able to Add and Remove derived objects to a list of Employees in some fashion, given the following example:
List<Employee> employees = new List<Employee>();
ProductionWorker _pWorker = new ProductionWorker();
_pWorker.Name = "Bob";
_pWorker.EmployeeID = 1234;
employees.Add(_pWorker));
I don't know if that's even possible or realistic to do that, but it would seem maybe there is a way from what I've read, I'm just not sure how to implement it. I'm open to better suggestions however, if someone knows of a better or proper way to get all the Employees listed into a ListBox without having to cycle through 3 different lists of the different derived classes.
For clarity, below is the Base class, then its following derived classes.
public class Employee
{
public string Name { get; set; }
public int EmployeeNumber { get; set; }
}
class ProductionWorker : Employee
{
public int ShiftNumber { get; set; }
public decimal HourlyPayRate { get; set; }
}
class TeamLeader : ProductionWorker
{
public int ReqHours { get; set; }
public int AttendedHours { get; set; }
}
class ShiftSupervisor : Employee
{
public int Salary { get; set; }
public int AnnualProductionBonus { get; set; }
}
I didn't realize until I posted my classes here that Team Leader is actually a derived class of Production Worker. I'm not sure if that changes things...
Yes, you can add Employee items and items deriving from Employee to the employees list.
List<Employee> employees = new List<Employee>();
ProductionWorker pWorker = new ProductionWorker {
Name = "Bob",
EmployeeID = 1234
};
employees.Add(pWorker);
If you want to display all these different kinds of employees in the same listbox, override the ToString method in these classes. The ListBox will automatically use it in order to display the items.
public class ProductionWorker : Employee
{
public override string ToString()
{
return String.Format("{0} ({1}), production", Name, EmployeeID);
}
}
You can assign the list of employees to the listbox like this
employeeListBox.DataSource = employees;
From the employees list you can access the members declared in Employee directly:
int id = employees[i].EmployeeID;
However; you need to cast, if you want to access members of derived types
int salary = 0;
var supervisor = employees[i] as ShiftSupervisor;
if (supervisor != null) {
salary = supervisor.Salary;
}
If you know the type of an item in advance you can cast directly
int salary = ((ShiftSupervisor)employees[0]).Salary;
Based off of the example located here:
Multiple ViewModels in View
Can anyone show this example without adding the individual items but by showing a datasource. So for instance if my business Logic layer has the means to pull the customer address then my two models would be CustomerInfo & CustomerLocations - doing it this way I am having trouble with the last line shown (the .Add) .. I tried removing the ToList but either way it says I have invalid arguements - my ViewModel class looks exactly like the example.
var ccus = new List<ViewModel.CustomerInfo>();
var cloc = new List<ViewModel.CustomerLocations>();
var cust = new ViewModel.Customers();
var cI1 = new Business.CustomerLogic.BLCustomerAddress();
cI1.LoadCustomerAddress(decryConcept, decryBnumber, intCustid).ToList();
ccus.Add(cI1);
In the previous example he declares the code inline
var car1 = new Car
{
Id = 1,
Name = "Passat"
};
I want to replace this piece with a call to my Business Logic
I have no reference to the BusinesLogic model in the new ViewModel I have setup per the example and perhaps this is where I need to tie the two objects together. Here is my code for that piece.
public class ViewModel
{ public class Customers
{ public IEnumerable<CustomerInfo> CInfo { get; set; }
public IEnumerable<CustomerLocations> CLoc { get; set; }
}
public class CustomerInfo
{
public int CustomerID { get; set; }
public string AccountNo { get; set; }
public bool Active { get; set; }
public string Company { get; set; }
.........
ccus is of type List<ViewModel.CustomerInfo> so the add method expects a ViewModel.CustomerInfo but you are passing in cI1 which is of type Business.CustomerLogic.BLCustomerAddress. Calling ToList() won't do anything as you are not storing the result of LoadCustomerAddress, so turning the result into a list has no affect on anything.
I'm stuck in my inheritances bloating here:
First let me explain the premise of my problem.
My Model:
public class Person
{
[Key]
public int PersonId { get; set; }
[MaxLength(100)]
public string Name { get; set; }
}
public class SuperHero:Person
{
[MaxLength(100)]
public string SuperHeroName { get; set; }
public virtual ICollection<SuperPower> SuperPowers{ get; set; }
}
Now, I am trying to create my viewModels for my MVC website, I have those base classes that need to be inherited by all other viewmodel displaying/editing a Person/SuperHero:
public class BasePersonViewModel
{
public string Name { get; set; }
ctors()
}
public class BaseSuperHeroViewModel : BasePersonViewModel
{
public List<string> SuperPowers{ get; set; }
ctors()
}
Here is where I am stuck, I am trying to define only one ViewModel that could be used regarless of the base class and access property of Person and/or SuperHero (if the Person is a superhero). I've been pulling my hair out but so far only found a solution which i don't like:
Example:
public class SomeViewModel<T> where T : BasePersonViewModel
{
public BasePersonViewModel obj;
public DateTime BirthDate { get; set; }
public SomeViewModel(Person data) //: base(data)
{
if (data is SuperHero)
obj = new BaseSuperHeroViewModel (data);
else
obj = new BasePersonViewModel(data);
}
}
While this would work it's really not sexy to use. And on top of that, I could have another ViewModel that inherit from SomeViewModel as well.
Is there a cleaner way to achieve this?
Edit
My main goal is to be able to able to cast my SomeViewModel depending on the one of the baseclass. Let's say do something like in my Controller:
if myclass is SomeViewModel (of type SuperHero)
Exactly how you do it for Person/SuperHero db retrival/check
var data = context.Person.first(w=> w.Id==1)
if (data is SuperHero)
..
I would like this because I would like to use the same viewmodel let's say to list superhero and person, and just display slightly differently if it's a superhero
Edit 2
I was trying to avoid using the whole Model.Obj to be able to see it directly with the Model... But the more i think about it, the more I think this is not possible really... On top of that I would like to extend some other superHero specific properties in SomeViewModel (only if SomeViewModel is a superhero), that are not declared in the BaseSuperHeroModel one... Let's say in SomeViewModel I want the field 'ComesFromPlanet' only if superhero.
Edit 3
I thought about another way to do it, but it obviously creating various ViewModel.
For the most general case (all fields that are shared for all Person) I would keep my base:
public class BasePersonViewModel
{
public string Name { get; set; }
ctors()
}
I interface specific Person:
public Interface IBaseSuperHero
{
[MaxLength(100)]
public string SuperHeroName { get; set; }
public List<string> SuperPowers{ get; set; }
}
I would keep as well OtherViewModel like this:
public class SomeViewModel:BasePersonViewModel
{
Public datetime Birthdate {get;set;}
}
Then I would create a specific SomeviewModel for other Person inheritant and used interfaces to have old and new properties.
For example:
public class SomeViewModelSuperHero:SomeViewModel, IBaseSuperHero
{
public string OriginalPlanet {get;set;}
}
Is this a clean solution?
Sorry I'm sure I am not clear about this, but I try !
Thanks for your input and time.
I am trying to define only one ViewModel that could be used regarless of the base class and access property of Person and/or SuperHero (if the Person is a superhero)
Assuming you'd return default values for super-hero properties when the model is not a super-hero, you could do something like this:
public class PersonOrSuperHeroViewModel {
private Person person;
private SuperHero superHero;
public PersonOrSuperHeroViewModel(Person personOrSuperHero) {
if (personOrSuperHero is SuperHero) superHero = personOrSuperHero;
person = personOrSuperHero;
}
public IsSuperHero { get { return superHero != null; } }
... // super-hero properties only work when IsSuperHero == true
}
How about something like
public class Person {
public virtual BasePersonViewModel MainViewModel {
get { return new BasePersonViewModel(this);}
}
}
public class SuperHero : Person {
public override BasePersonViewModel MainViewModel {
get { return new BaseSuperHeroViewModel(this);}
}
}
So if all your people classes override the MainViewModel property to return the appropriate view, you don't need
public BasePersonViewModel obj;
public SomeViewModel(Person data) {
if (data is SuperHero)
obj = new BaseSuperHeroViewModel (data);
else
obj = new BasePersonViewModel(data);
}
Because you can have
public BasePersonViewModel obj;
public SomeViewModel(Person data) { obj = data.MainViewModel; }
which will work however many subclasses of person you have.
I have the following problem (simplified).
I have a list of dogs:
public List<Dog> dogs { get; set; }
I currently access this list as a json object by converting it in a view:
#(new HtmlString(#Json.Encode(#ViewBag.dogs)))
I then iterate through this json object using javascript and display it on a page.
I would like to add cars to this list.
However, since the list is strongly typed as a list of dogs my first thought was to create the list as the one thing dogs and cars have in common, they're both objects.
When I tried to change my list of dogs into a list of objects, I received the following error
Cannot implicitly convert type 'System.Collections.Generic.List<object>' to System.Collections.Generic.List<dog>
I researched that and found this question which didn't help me much except to tell me that I would not be able to have a list of dogs and cars. For my purposes, however, this isn't suitable. I need my list to contain both dogs and cars, so that I have access to both of them in my application.
One solution I anticipate being suggested is that I have two separate lists, and make two separate ajax requests. However, I need to mix cars and dogs in a specific order (based on the time they were created essentially) so that solution isn't ideal.
In short, I'm wondering what the best way to accomplish this is. Perhaps I've gone off in completely the wrong direction, so I'm not opposed to doing something completely different if it makes sense.
Thanks for the help as always!
EDIT: I've tried the cast and that works. However, I need to access a property of dog (let's call it "fur") and I don't seem to be able to do that (do I need to cast again?)
'object' does not contain a definition for 'fur'
You can make list that contains both dogs and cars only if they implement the same interface or extends same class (e.g. object, then you can use typeof in condition to perform some actions on them).
EDIT:
Simple example
using System;
using System.Collections.Generic;
namespace Polymorphism
{
class Program
{
public class Car
{
public string Drive()
{
return "Wrrrr!";
}
}
public class Dog
{
public string Talk()
{
return "Woof";
}
}
static void Main()
{
var car = new Car();
var dog = new Dog();
List<object> list = new List<object>();
list.Add(car);
list.Add(dog);
foreach (object o in list)
{
if (o is Car)
Console.WriteLine((o as Car).Drive());
else
Console.WriteLine((o as Dog).Talk());
}
}
}
}
I'm sorry for that code but I copied it from Wikipedia and edited using Ideone
It's not really clear to me where the cars come in, and why you can't just change your property to be a List<object> to start with, but you can do:
List<object> objects = foo.Dogs.Cast<object>().ToList();
or in C# 4, you could use generic covariance and just write:
List<object> objects = foo.Dogs.ToList<object>();
The simplest way to have different objects in a list and access a property that they have in common is to use an Interface on the classes.
For example:
public interface ICoated {
string Coating { get; set; }
}
public class Dog : ICoated {
public string Coating {
get { return Fur; }
set { Fur = value; }
}
}
public class Car: ICoated {
public string Coating {
get { return PaintJob; }
set { PaintJob = value; }
}
}
You would then use a List<ICoated> in order to access objects that are all coated with something. Obviously, if you have many common attributes, you would then extend this model appropriately.
try to work out what's common between the two objects and use either a base class or an interface. if you used an interface, you might have it looking like this:
public interface IAnimal{
Fur Fur{ get; set; }
bool CanBark { get; set;}
}
public class Dog : IAnimal {
public Fur Fur{ get; set; }
public bool CanBark { get; set;}
}
public class Cat: IAnimal {
public Fur Fur{ get; set; }
public bool CanBark { get; set;}
}
public class Fur{
public string Color {get;set;}
public int Length {get;set}
}
etc, etc
then, your lists can be:
public List<IAnimal> dogs { get; set; }
public List<IAnimal> cats{ get; set; }
(pet) food for thought
I would probably make an interface that has shared properties, and a "Type" property.
public enum CrazyObjectType
{
Dog,
Car
}
public interface ICrazyObject
{
DateTime Date { get; }
CrazyOjbectType MyObjectType { get; }
}
public class Dog : ICrazyObject
{
public Dog()
{
MyObjectType = CrazyObjectType.Dog;
}
public DateTime Date { get; }
public CrazyObjectType MyObjectType { get; }
}
public class Car : ICrazyObject
{
public Car()
{
MyObjectType = CrazyObjectType.Car;
}
public DateTime Date { get; }
public CrazyObjectType MyObjectType { get; }
}
Then instead of List<object> you can have a List<ICrazyObject> that you check for type before casting to a car or a dog..
foreach (var myObject in myObjects)
{
if (myObject.MyObjectType == CrazyObjectType.Car)
{
var myCar = (Car)myObject;
//Do Stuff with myCar here.
}
}
This gives you the safety of knowing your type before casting it. Then whatever properties you have in type car that are different than dog. You can access easily, and safely!