Autofixture: Randomly fill property of a class - c#

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

Related

Creating a property class with no default value and with value

I'm trying to create a property class with a default value and no value. Is this right? If I want a property with no value I'll just call GameLevel class and if I want a property with default value I'll just call GameLevelWithDefaultValue
public abstract class GameLevel
{
public abstract int nextLevelToUnlock { get; set; }
public abstract List<LevelDetails> levelDetails { get; set; }
}
class GameLevelWithDefaultValue : GameLevel
{
public override int nextLevelToUnlock { get; set; } = 1;
public override List<LevelDetails> levelDetails { get; set; } = new List<LevelDetails>()
{
new LevelDetails{levelIndex = 1, Stars = 0 },
new LevelDetails{levelIndex = 2, Stars = 0 },
new LevelDetails{levelIndex = 3, Stars = 0 }
};
}
public class LevelDetails
{
public int levelIndex { get; set; }
public int Stars { get; set; }
}
I meant something like this:
public class GameLevel
{
public int NextLevelToUnlock { get; set; }
public List<LevelDetails> LevelDetails { get; set; }
public GameLevel() { }
public GameLevel(int nextLevelToUnlock, List<LevelDetails> levelDetails)
{
NextLevelToUnlock = nextLevelToUnlock;
LevelDetails = levelDetails;
}
}
public class LevelDetails
{
public int LevelIndex { get; set; }
public int Stars { get; set; }
public LevelDetails(int levelIndex, int stars)
{
LevelIndex = levelIndex;
Stars = stars;
}
}
public static class GameLevelBuilder
{
public static GameLevel BuildGameLevelWithDefaultValue()
{
var defaultLevelDetail = new List<LevelDetails>()
{
new LevelDetails(1, 0),
new LevelDetails(2, 0),
new LevelDetails(3, 0)
};
return new GameLevel(1, defaultLevelDetail);
}
}
When you need the object with the default value, you'll let the GameLevelBuilder create the object for you, while when you need the object without passing the initial values, you'll use the parameterless constructor of GameLevel.
You cannot instantiate an abstract class. If you inherit an abstract class, you must override it's abstract properties. So, the value of nextLevelToUnlock and levelDetails depends on the child class.
Also, default value for class in C# is null, or the result of it's zero parameter constructor for value types. If you don't assign any value to a field, it will get it's default value.

C# complex class constructors

I have the following system: a "mother" class called DataClass, has properties and two of them are classes, PartClass and MemberClass. In particular, MemberClass has properties and one of them is a class, SideClass - with its own properties.
Here is the code sample:
using System;
namespace ConsoleApp
{
public class DataClass
{
public int num { get; set; }
public string code { get; set; }
public PartClass part { get; set; }
public MemberClass member { get; set; }
public DataClass()
{
PartClass part = new PartClass();
MemberClass member = new MemberClass();
}
}
public class PartClass
{
public int seriesNum { get; set; }
public string seriesCode { get; set; }
public PartClass() { }
}
public class MemberClass
{
public int versionNum { get; set; }
public SideClass side { get; set; }
public MemberClass()
{
SideClass side = new SideClass();
}
}
public class SideClass
{
public string firstDetail { get; set; }
public string secondDetail { get; set; }
public bool include { get; set; }
public SideClass() { }
}
Now, I am trying to initialize the DataClass and assign values to all properties, and this doesn't work.
So, the DataClass "owns" the PartClass and the MemberClass and the MemberClass itself "sees" the SideClass which is the bottom class and sort of independent of all.
Here the rest of code:
class Program
{
static void Main(string[] args)
{
DataClass myData = new DataClass()
{
num = 13,
code = "message",
//from here downwards nothing works; error..
part.seriesNum = 1,
part.seriesCode = 7,
member.versionNum = 9,
member.side.firstDetail = "pass",
member.side.secondDetail = "checked",
member.side.include = true;
}
}
}
I thought that by installing constructors and properties the DataClass instantiation would not have problems, but actually the DataClass does not see any non-trivial properties (properties referring to classes).
Could someone help me please? Thank you..
Use following :
DataClass myData = new DataClass()
{
num = 13,
code = "message",
part = new PartClass()
{
seriesNum = 1,
//here down nothing works; error
seriesCode = "abc"
},
member = new MemberClass()
{
versionNum = 9,
side = new Side()
{
firstDetail = "pass",
secondDetail = "checked",
include = true
}
}
};
To not have to create the instance of Member Class and Part Class manually every time, you can create the instances using get and set methods.
public class DataClass
{
public int num { get; set; }
public string code { get; set; }
private PartClass _part;
public PartClass part { get { if (_part == null) _part = new PartClass(); return _part; } set { _part = value; } }
private MemberClass _member;
public MemberClass member { get { if (_member == null) _member = new MemberClass(); return _member; } set { _member = value; } }
}
you should create an instance of DataClass then initialize fields
DataClass myData = new DataClass();
myData.num = 13,
myData.code = "message",
myData.part.seriesNum = 1,
myData.part.seriesCode = 7,
myData.member.versionNum = 9,
myData.member.side.firstDetail = "pass",
myData.member.side.secondDetail = "checked",
myData.member.side.include = true;

Automapper - mapping InnerDestination to OuterSource

I've followed the nested example from the Automapper Wiki but I'm having some trouble extending it. In the code below, I'm trying to map InnerDest2 to OuterSource. Specifically, I want InnerDest2.Value to be populated with OuterSource.Value but when I run, InnerDest2 comes back as null. I'm sure there is something simple I'm missing, but I just can't figure it out.
Any ideas?
namespace AutomapNestTest
{
class Program
{
static void Main(string[] args)
{
ConfigureAutomapper();
var source = new OuterSource
{
Value = 5,
Inner = new InnerSource { OtherValue = 15 },
};
var dest = new OuterDest();
AutoMapper.Mapper.Map(source, dest);
}
private static void ConfigureAutomapper()
{
AutoMapper.Mapper.Initialize(cfg =>
{
cfg.CreateMap<OuterSource, OuterDest>();
cfg.CreateMap<InnerSource, InnerDest>();
cfg.CreateMap<OuterSource, InnerDest2>();
});
}
}
public class OuterSource
{
public int Value { get; set; }
public InnerSource Inner { get; set; }
}
public class InnerSource
{
public int OtherValue { get; set; }
}
public class OuterDest
{
public int Value { get; set; }
public InnerDest Inner { get; set; }
public InnerDest2 Inner3 { get; set; }
}
public class InnerDest
{
public int OtherValue { get; set; }
}
public class InnerDest2
{
public int Value { get; set; }
}
}
You are mapping an OuterSource object to an OuterDesc object. There is a mapping configuration from OuterSource to InnerDest2 but there is no property of type OuterSource inOuterSource itself so there is no way for the propertyInner3 in OuterDest to be mapped from anything.
If you need the source.Value to be mapped to dest.Inner3.Value, you would have to do another mapping explicitly. First declare the variable:
var innerDest2 = new InnerDest2();
After this, do the mapping and set the dest.Inner3:
AutoMapper.Mapper.Map(source, innerDest2);
dest.Inner3 = innerDest2;

Match names in list with elements in class

I wonder if there's any way to match the names in a list with the elements in a class:
I have a class:
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
and a List: List<exampleClass> EnfSist
So that's the way the list is made. Now I would like to know how to match or identify the string inside "name" from my list. To match this class:
tbl_sistematicas b = new tbl_sistematicas
{
ap_enf_id_enfermedad = Convert.ToInt32(EnfSist[0].value),
ap_pac_inicio = Convert.ToInt32(EnfSist[1].value),
ap_pac_inicio_periodo = Convert.ToInt32(2].value),
ap_pac_duracion = Convert.ToInt32(EnfSist[3].value),
ap_pac_duracion_periodo = Convert.ToInt32(EnfSist[4].value),
ap_pac_tratamiento = EnfSist[5].value
};
Once being able to match the same names I won't have to specify each index of every element in the list. The elements in the list have the same name as in the table. Not all elements of the class are being used.
I have something like this: tbl_sistematicas bh = EnfSist.FindAll(x => x.name == bh.?????? );
If I understand the question, you can do this using something like automapper or ValueInjector
An example using ValueInjector
void Main()
{
List<exampleClass> EnfSist = new List<exampleClass>();
EnfSist.Add(new exampleClass { name = "ap_enf_id_enfermedad", value = "12" });
EnfSist.Add(new exampleClass { name = "apap_pac_inicio" , value = "34" });
// etc
tbl_sistematicas b = new tbl_sistematicas();
b.InjectFrom<MyInjection>(EnfSist);
}
public class MyInjection : KnownSourceValueInjection<List<exampleClass>>
{
protected override void Inject(List<exampleClass> source, object target)
{
foreach(var entry in source)
{
var property = target.GetProps().GetByName(entry.name, true);
if (property != null)
property.SetValue(target, Convert.ChangeType(entry.value, property.PropertyType));
}
}
}
public class exampleClass
{
public string name { get; set; }
public string value { get; set; }
}
public class tbl_sistematicas
{
public int ap_enf_id_enfermedad { get; set; }
public int apap_pac_inicio { get; set; }
public int ap_pac_inicio_periodo { get; set; }
public int ap_pac_duracion { get; set; }
public int ap_pac_duracion_periodo { get; set; }
public string ap_pac_tratamiento { get; set; }
}
Note, this will throw an exception if the value can not be converted to an int

Extend base class properties

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);
}
}

Categories