Extend base class properties - c#

I need your help to extend my base class, here is the similar structure i have.
public class ShowRoomA
{
public audi AudiModelA { get; set; }
public benz benzModelA { get; set; }
}
public class audi
{
public string Name { get; set; }
public string AC { get; set; }
public string PowerStearing { get; set; }
}
public class benz
{
public string Name { get; set; }
public string AC { get; set; }
public string AirBag { get; set; }
public string MusicSystem { get; set; }
}
//My Implementation class like this
class Main()
{
private void UpdateDetails()
{
ShowRoomA ojbMahi = new ShowRoomA();
GetDetails( ojbMahi ); // this works fine
}
private void GetDetails(ShowRoomA objShowRoom)
{
objShowRoom;
objShowRoom.audi = new audi();
objShowRoom.audi.Name = "AUDIMODEL94CD698";
objShowRoom.audi.AC = "6 TON";
objShowRoom.audi.PowerStearing = "Electric";
objShowRoom.benz= new benz();
objShowRoom.benz.Name = "BENZMODEL34LCX";
objShowRoom.benz.AC = "8 TON";
objShowRoom.benz.AirBag = "Two (1+1)";
objShowRoom.benz.MusicSystem = "Poineer 3500W";
}
}
// Till this cool.
// Now I got requirement for ShowRoomB with replacement of old audi and benz with new models and new other brand cars also added.
// I don't want to modify GetDetails() method. by reusing this method additional logic i want to apply to my new extended model.
// Here I struck in designing my new model of ShowRoomB (base of ShowRoomA) ... I have tried some thing like... but not sure.
public class audiModelB:audi
{
public string JetEngine { get; set; }
}
public class benzModelB:benz
{
public string JetEngine { get; set; }
}
public class ShowRoomB
{
public audiModelB AudiModelB { get; set; }
public benzModelB benzModelB { get; set; }
}
// My new code to Implementation class like this
class Main()
{
private void UpdateDetails()
{
ShowRoomB ojbNahi = new ShowRoomB();
GetDetails( ojbNahi ); // this is NOT working! I know this object does not contain base class directly, still some what i want fill my new model with old properties. Kindly suggest here
}
}
Can any one please give me solutions how to achieve my extending requirement for base class "ShowroomA"
Really appreciated your time and suggestions.
Thanks in advance,

The problem is here:
private void GetDetails(ShowRoomA objShowRoom)
{
objShowRoom = new objShowRoom(); //<-----
You're not using the object you passed in - instead you're creating a NEW object and using it. just remove
objShowRoom = new objShowRoom();
and fix this block:
objShowRoom.benz= new benz();
objShowRoom.audi.Name = "BENZMODEL34LCX"; //<--- should be objShowRoom.benz?
objShowRoom.audi.AC = "8 TON";
objShowRoom.audi.AirBag = "Two (1+1)";
objShowRoom.audi.MusicSystem = "Poineer 3500W";
and you should be fine.

I would create a Car class for starters:
public class Car
{
public string Name { get; set; }
public string AC { get; set; }
public string PowerStearing { get; set; }
public string MusicSystem { get; set; }
}
public class Audi : Car
{
}
public class Benz : Car
{
}
And a ShowRoom class, with a list of Car:
public class ShowRoomA
{
public List<Car> Cars { get; set; }
public virtual void GetDetails(ShowRoomA showRoom)
{
// Do your stuff
}
}
Which you could extend as well:
public class ShowRoomB : ShowRoomA
{
public override void GetDetails(ShowRoomA showRoom)
{
// Do some other stuff
}
}
And use as such:
class Main()
{
private void UpdateDetails()
{
ShowRoom ojbMahi = new ShowRoom();
Audi audi = new Audi() { Name = "AUDIMODEL94CD698", AC = "6 TON" };
objMahi.Cars.Add(audi);
Benz benz = new Benz() { Name = "BENZMODEL34LCX", AC = "8 TON" };
objMahi.Cars.Add(benz);
}
}

Related

Autofixture: Randomly fill property of a class

Concering the following class:
public partial class ByValueCondition
{
public ParameterCondition ParameterCondition { get; set; }
public TimeOfDayCondition TimeOfDayCondition { get; set; }
public SimulationTimeCondition SimulationTimeCondition { get; set; }
public StoryboardElementStateCondition StoryboardElementStateCondition { get; set; }
public UserDefinedValueCondition UserDefinedValueCondition { get; set; }
public TrafficSignalCondition TrafficSignalCondition { get; set; }
public TrafficSignalControllerCondition TrafficSignalControllerCondition { get; set; }
}
I want a customization in autofixture that will randomly only choose one property and fill it, while leaving the other ones blank. The configuration of the underlying classes should be still defined by the global customizations of the fixture.
Also it should be possible to create a Collection of ByValueCondition.
I tried around with this but cant find an easy solution except creating a ISpecimenbuilder from the ground up.
I would personally do it with following schema:
// Interface implemented by all Conditions
public interface ICondition
{
bool IsConditionTrue(object ObjectThatWeKnow);
}
// Your object
public partial class ByValueCondition
{
public ICondition Condition { get; set; }
}
// And here you define all types of conditions
public class ParameterCondition : ICondition
{
public object Parameter { get; set; }
public bool IsConditionTrue(object ObjectThatWeKnow)
{
return ObjectThatWeKnow.Equals(Parameter);
}
}
public class TimeOfDayCondition : ICondition
{
public bool IsConditionTrue(object ObjectThatWeKnow) { return true; }
}
public class SimulationTimeCondition : ICondition
{
public bool IsConditionTrue(object ObjectThatWeKnow) { return true; }
}
And the randomness you could do as:
var conditions = new List<ICondition>()
{
new ParameterCondition() { Parameter = "whatever" },
new ParameterCondition() { Parameter = "otherString" },
new ParameterCondition() { Parameter = "NextOne" },
new TimeOfDayCondition() { TimeBefore = DateTime.Now },
new TimeOfDayCondition() { TimeAfter = DateTime.Now.AddDays(-1) },
}
var rand = new Random();
var randomN = rand.Next(0, conditions.Count);
var byValueCondition = new ByValueCondition();
byValueCondition.Condition = conditions[randomN]; //Here you assign random value

Assigning data from a class list to another class list

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.

How to handle same code parts in Factory Method?

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.

How to go about combining two objects, manipulate the data, then separate them?

I have two classes with some similar fields, some different, and a form that utilizes two different objects depending on what mode it's in (insert/edit).
Instead of using two different objects and if statements checking the form mode, I'd like to have one struct to be hydrated with either of the two objects fields so I can manipulate one object through the page life-cycle. Then separated the struct back to its respective object for insert/updating the DB.
Example of classes:
public partial class SomeClass
{
public Int32 B {get;set;}
public String C {get;set;}
public Boolean D {get;set;}
}
public class SomeOtherClass
{
public Int32 A {get;set;}
public Int32 B {get;set;}
public String C {get;set;}
}
Update with Solution Example:
public interface IInsertable
{
string SharedName { get; set; }
string SharedID { get; set; }
string editedFieldValue { get; set; }
long GetSuperSecreteInfo();
}
internal class InsertableImplementation : IInsertable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return -1;
}
}
public interface IUpdateable
{
string SharedName { get; set; }
string SharedID { get; set; }
string updatedFieldValue { get; set; }
Guid GenerateStevesMagicGuid();
}
internal class UpdateableImplementation : IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
public static class WonderTwinFactory
{
public static WonderTwins GenerateWonderTwin(IUpdateable updateable, IInsertable insertable)
{
var wt = new WonderTwins();
// who will win?
wt.SharedID = updateable.SharedID;
wt.SharedID = insertable.SharedID;
// you decide?
wt.SharedName = updateable.SharedName;
wt.editedFieldValue = "stuff";
return wt;
}
}
public class WonderTwins : IInsertable, IUpdateable
{
public string SharedName { get; set; }
public string SharedID { get; set; }
public string editedFieldValue { get; set; }
public long GetSuperSecreteInfo()
{
return 1;
}
public string updatedFieldValue { get; set; }
public Guid GenerateStevesMagicGuid()
{
return new Guid();
}
}
class Program
{
static void Main(string[] args)
{
IUpdateable updateable = new UpdateableImplementation();
IInsertable insertable = new InsertableImplementation();
WonderTwins dualImplementatin = WonderTwinFactory.GenerateWonderTwin(updateable, insertable);
IUpdateable newUpdateable = dualImplementatin as IUpdateable;
IInsertable newInsertable = dualImplementatin as IInsertable;
}
}
Have both classes implement an interface that defines the operations common to each, including both the fields that are shared (assuming the view needs to access them) and also a method to actually perform the operation that they represent (insert/edit).
Other way of doing such things is using C# dynamic object and assign properties directly. It may help to avoid any new type or interface and directly utilizing new dynamic object any time, as much as required.
var newObject = new {
objectOfClass1 = x.prop1,
objectOfClass2 = x.prop2
}

AutoMapper - Map a complex object using naming conventions without providing inner mappings

I have two complex objects that have exactly the same properties.
Now with AutoMapper, I usually will need to do something like this:
Mapper.CreateMap<ObjA, ObjB>();
But if one of the objects has a complex inner object, Ill need to map it too:
Mapper.CreateMap<ObjAInner, ObjBInner>();
Now I have a large object that expands all the time.
I don't want to maintain the CreateMap calls each time I add a complex inner object to the main object.
Now I can probably solve this with a recursive reflection on the main object and map all the types but I'd prefer not to do that.
Is there anyway I can tell AutoMapper to Create a full recursive map(also for inner types) on a complex object?
Something like this:
Mapper.CreateFullMapOnIdenticalObjectsWithInnerTypes<ObjA, ObjB>();
Edit:
Here's an example:
two identical classes with a different namespace:
namespace NameSpace1
{
public class Obj1
{
public string Str { get; set; }
public int Num { get; set; }
public InnerObj1 InnerObj1 { get; set; }
}
public class InnerObj1
{
public string StrInner1 { get; set; }
public int NumInner1 { get; set; }
public AnotherInnerObj1 AnotherInnerObj1 { get; set; }
}
public class AnotherInnerObj1
{
public string Str { get; set; }
}
}
namespace NameSpace2
{
public class Obj1
{
public string Str { get; set; }
public int Num { get; set; }
public InnerObj1 InnerObj1 { get; set; }
}
public class InnerObj1
{
public string StrInner1 { get; set; }
public int NumInner1 { get; set; }
public AnotherInnerObj1 AnotherInnerObj1 { get; set; }
}
public class AnotherInnerObj1
{
public string Str { get; set; }
}
}
Create a mock NameSpace1.Obj1:
public static NameSpace1.Obj1 Create()
{
return new NameSpace1.Obj1
{
Num = 10,
Str = "Obj1",
InnerObj1 = new NameSpace1.InnerObj1
{
NumInner1 = 11,
StrInner1 = "InnerObj1",
AnotherInnerObj1 = new NameSpace1.AnotherInnerObj1
{
Str = "AnotherInnerObj1"
}
}
};
}
This is what I would like:
Mapper.CreateMap<NameSpace1.Obj1, NameSpace2.Obj1>();
var obj1 = Create();
var obj2 = Mapper.Map<NameSpace2.Obj1>(obj1);
But this will throw an exception since I need to define inner mappings. This will work:
Mapper.CreateMap<NameSpace1.Obj1, NameSpace2.Obj1>();
Mapper.CreateMap<NameSpace1.InnerObj1, NameSpace2.InnerObj1>();
Mapper.CreateMap<NameSpace1.AnotherInnerObj1, NameSpace2.AnotherInnerObj1>();
var obj1 = Create();
var obj2 = Mapper.Map<NameSpace2.Obj1>(obj1);

Categories