I want ton assign the object dynamically based on the condition, i was not allowed to create variable without declaration.
var carSegment;
switch (segmentType)
{
case "CarSeg":
carSegment = new CarSeg();
break;
case "NonAirSeg":
carSegment = new NonAirSeg();
break;
}
In order to do this, both CarSeg and NonAirSeg need to share an interface or a base class, which would be the type for carSegment. For example, if they both implement an interface called ISegment, then you could do this:
ISegment carSegment = null;
Then the assignments in your switch statement would work in their current state. The same is true if they implement a common ancestor class.
The catch is that carSegment is that common type and only that common type. If you need specifics to those two different types then you'd probably need to re-think your design outside the scope of this one code segment.
Related
Imagine a part of your state machine looks like this:
How do you properly implement the choice part in Qt? I know there are guarded transitions, but that would mean that I need to:
Create a subclass of a QAbstractTransition which accepts e.g. an std::function<bool()> and a flag which determines if the transition happens when that boolean result is true, or when it is false
Create two instances of this class with the same boolean function, but opposite transition guards
Add two transitions from S1 using these two instances.
That approach seems kind of clumsy and error prone for something as simple as a choice.
Is there a more maintainable approach to implement this?
License Notice:
Alternatively to the default StackOverflow license you are hereby allowed to use this code through the MIT License.
I've created a BooleanChoiceTransition class with a constructor like this (might contain errors, the code is not on this machine, so I typed it by heart):
BooleanChoiceTransition::BooleanChoiceTransition(std::function<bool()> choiceFunc, QState* targetForTrueCase, QState* targetForFalseCase)
: QState{}
{
this->addTransition(this, &BooleanChoiceTransition::transitionToTrueTarget, targetForTrueCase);
this->addTransition(this, &BooleanChoiceTransition::transitionToFalseTarget, targetForFalseCase);
(void)QObject::connect(this, &QAbstractState::entered, [this]() {
if(choiceFunc())
{
emit transitionToTrueTarget();
}
else
{
emit transitionToFalseTarget();
}
});
}
with transitionToTrueTarget and transitionToFalseTarget being signals of course.
For the case of the example in the question, the class can be used like so:
auto choiceState = new BooleanChoiceTransition([this](){ return _someConditionFullfilled; }, s2, s3);
s1->addTransition(this, &MyClass::someTrigger, choiceState);
Since BooleanChoiceTransition is a QState, this can even be nested easily:
auto outerChoiceState = new BooleanChoiceTransition([this](){ return _someOtherConditionFullfilled; }, s4, choiceState);
I am developing an application for generating estimates on products such as cars.
So, when a car make an model is selected, I need to present various options to the user (options may be in different groups like Wheels, Seating Upholstery, Trunk Accessories)
Depending upon the group, the customer may pick one or more options in that group; if a certain option is selected - some other options may get disabled; not all options apply to every make an model
So, there are several rules to be defined for different groups to indicate what combination is allowed and what is not allowed?
How should I go about designing the database for this and is there a pattern that I can leverage as I develop this application?
I solved a similar requirement with the following structure, rewritten in your terms above:
Parts
Groups
Car
With the following notes:
Parts are standalone in their own right, each with a part number.
A car template is standalone in its own right.
Parts can be added to a option group, and a number of options groups belongs to a car.
An option group cannot exist without a car.
A group can depend on another group
I need to protect against circular references
I started out playing with my model by writing the test case before i wrote the class code (Test Driven Development), which gave me code (in C#) as:
var dieselEngine = new Sku("diesel 2_litre,",1000);
var petrolEngine2 = new Sku("petrol_2_litre",800);
var petrolEngine25 = new Sku("petrol_25_litre",900);
var petrolTurbo = new Sku("petrol_turbo",2000);
var dieselTurbo = new Sku("diesel_turbo",2000);
var car = new Car("myCar");
car.AddGroup("Engines");
car.AddSkuToGroup("Engines", diselEngine);
car.AddSkuToGroup("Engines", petrolEngine2);
car.AddSkuToGroup("Engines", petrolEngine25);
car.AddGroup("Turbos");
car.AddSkuToGroup("Turbos", petrolTurbo);
car.AddSkuToGroup("Turbos", dieselTurbo);
car.SetRequirement(diselEngine, dieselTurbo);
car.SetRequirement(petrolTurbo, petrolEngine2);
car.SetRequirement(petrolTurbo, petrolEngine25);
I add the dependency option on the groups, rather than on the Sku, since a part may exist across multiple cars but may have different dependencies for each specific car.
I have to put everything through the root car object, which will check and enforce all my business rules (such as checking for and protecting against circular references).
Should all access via the car object feel clunky, you could always have the car.AddGroup function return a group to make the code make more sense to read:
var engines = car.AddGroup("Engines");
engines.AddSkuToGroup(diselEngine);
engines.AddSkuToGroup(petrolEngine2);
engines.AddSkuToGroup(petrolEngine25);
But do not forget the business rules can only be enforced by the car, since the car has visibility of all the components. So we always chain up via the root:
class ConfigurableProduct
{
List<Group> groups = new List<Group>();
Group NewGroup(string name)
{
var group = new Group(this, name);
this.groups.Add(group);
return group;
}
bool ContainsSku(string skuId)
{
foreach (var group in this.Groups)
{
if (group.ContainsSku(skuId))
return true;
}
return false;
}
}
class Group
{
Group(ConfigurableProduct parent, string name)
{
this.parent = parent;
this.name = name;
}
string name;
List<string> skuIds = new List<string>();
ConfigurableProduct parent;
void AddSkuToGroup(string skuId)
{
// enforce invariants via parent, call functions as reuqired
if (this.parent.containsSku(skuId))
throw new Exception("SKU already exists in this configurable template, cannot exist twice");
// do other things, like check circular references etc, all via this.parent
}
bool ContainsSku(string toFind)
{
foreach (var skuId in this.skuIds)
{
if (skuId == toFind)
return true;
}
return false;
}
}
For the actual database storage i would worry about persistence last, it could be a text file, MSSQL database, MySQL database, MongoDB, there are so many options.
I find it always useful to concentrate on how i want to use the code in my application, and not the specifics of how the database needs to be used, as the storage can abstracted via a repository interface that returns a class (a plain old POCO class, but in this case we have started to flesh out with business logic to protect against invalid states).
For the front end, you may want to push this all down via JSON to something like angular or knockout that can render the options available dynamically, and show or hide different elements depending on the dependencies between groups.
Working fronted example
I am not sure what front end binding you are using (or if you will only be using razor, in that case you will need to store state on the server and refresh each selection), but I have provided an example using Knockoutjs here: http://jsfiddle.net/g18c/5jt9bwsv/1/ with working dependencies and dynamic javascript object builder.
Loops through provided JSON products by group
Creates calculated fields that change depending on a target dependency
Binds to a view via knockout
The selected SKUs could then simply be passed up to the server, any business rules can also be implemented in the front end javascript.
Of course anything data that is sent from the client to the server would need to be validated by building up the product graph on the server and checking that the provided SKUs are valid (i.e. you wouldn't want to allow a Diesel Turbo to be selected for a Petrol Engine).
I would like to change behavior of list page based on the menuitem which call is. I know I am able to call ListPage with different queries but I wan to go little further and have ListPage with different ListPageInteraction class or with ListPageInteraction class where I can have some arguments from menuitem which calls it. How can I do it?
I am adding range on ListPageQuery in ListPageInteraction class dynamically in initializeQuery method based on user which calls the list page.
I know I can have a duplicate of a ListPage with different ListPageInteraction assigned or I can artificially add some information to the _query but it does not seems right.
P.S.: Why there is no _args input?
The is an args input, check the SysListPageInteractionBase class, in the initializing method the args object is retrieved:
this.setListPageType(this.listPage().listPageArgs());
You change the query based on this, check the ReturnTableListPageInteraction.setModeledQueryName() method for example:
switch (this.getListPageType())
{
case ReturnTableListPageType::Main:
// Don't change query
break;
case ReturnTableListPageType::Open:
this.listPage().modeledQueryName(querystr(ReturnTableListPage_Open));
break;
[...]
}
Web services cannot return an anonymous type.
If you are building a LINQ query using classes through a datacontext... you cannot construct instances of those classes in a query.
Why would I want to do this? Say I want to join three "tables" or sets of objects. I have three items with a foreign key to each other. And say the lowest, most detailed of these was represented by a class that had fields from the other two to represent the data from those. In my LINQ query I would want to return a list of the lowest, most detailed class. This is one way I have decided to "join some tables together" and return data from each of them via LINQ to SQL via a WebService. This may be bad practice. I certainly do not like adding the additional properties to the lowest level class.
Consider something like this... (please ignore the naming conventions, they are driven by internal consideration) also for some reason I need to instantiate an anonymous type for the join... I don't know why that is... if I do not do it this way I get an error...
from su in _dataContext.GetTable<StateUpdate>()
join sfs in _dataContext.GetTable<SystemFacetState>()
on new { su.lngSystemFacetState } equals new { lngSystemFacetState = sfs.lngSystemFacetState }
join sf in _dataContext.GetTable<SystemFacet>()
on new { sfs.lngSystemFacet } equals new { lngSystemFacet = sf.lngSystemFacet }
join s in _dataContext.GetTable<System>()
on new { sf.lngSystem } equals new {lngSystem = s.lngSystem}
select new
{
lngStateUpdate = su.lngStateUpdate,
strSystemFacet = sf.strSystemFacet,
strSystemFacetState = sfs.strSystemFacetState,
dtmStateUpdate = su.dtmStateUpdate,
dtmEndTime = su.dtmEndTime,
lngDuration = su.lngDuration,
strSystem = s.strSystem
}
).ToList();
Notice I have to build the anonymous type which is composed of pieces of each type. Then I have to do something like this... (convert it to a known type for transport via the web service)
result = new List<StateUpdate>(from a in qr select(new StateUpdate
{
lngStateUpdate = a.lngStateUpdate,
strSystemFacet = a.strSystemFacet,
strSystemFacetState = a.strSystemFacetState,
dtmStateUpdate = a.dtmStateUpdate,
dtmEndTime = a.dtmEndTime,
lngDuration = a.lngDuration,
strSystem = a.strSystem
}));
It is just awful. And perhaps I have created an awful mess. If I am way way off track here please guide me to the light. I feel I am missing something fundamental here when I am adding all these "unmapped" properties to the StateUpdate class.
I hope someone can see what I am doing here so I can get a better way to do it.
You can create a 'dto' class which just contains the properties you need to return and populate it instead of the anonymous object:
public class Result
{
public string lngStateUpdate
{
get;
set;
}
... // other properties
}
then use it like this:
from su in _dataContext.GetTable<StateUpdate>()
...
select new Result
{
lngStateUpdate = su.lngStateUpdate,
... // other properties
}
Nitpick note - please ditch the Hungarian notation and camel casing for properties :)
I think the answer is to create another object to serve as a DTO. This object would not be mapped to the data context and can contain fields that cross the mapped objects. This solves the problems of repetitive properties in the mapped objects, and allows for instantiation of the DTO class in the query as it is not mapped.
FYI: with respect to the problem with the join- I revisited that and I think I may have had the inner and outer components of the join switched around before.
I have a plain textfield in Tridion that can have multiple values. The itemtype is a SingleLineTextField.
In the TBB code I have the following (removed the non-essential parts):
ItemFields itemFields = new ItemFields(folder.Metadata, folder.MetadataSchema);
foreach (ItemField itemField in itemFields)
{
string itemFieldValue = string.Empty;
switch (Utilities.GetFieldType(itemField))
{
case FieldType.SingleLineTextField:
itemFieldValue = itemField.ToString();
break;
}
}
Now the result in case of two entries is just two strings with a character line break in it.
String A
String B
The method used is a generic one, which also works on other fields, so I was looking for some way to find out if a SingleLineTextField has more values in it.
You can cast the field to a SingleLineTextField type, then iterate through the Values collection, something along these lines:
SingleLineTextField field = (SingleLineTextField)itemField;
foreach(string value in field.Values)
{
// do something with value
}
// or if all you want is the count of values
int i = field.Values.Count;
Firstly, I would advise against relying on the ToString() method on objects unless it is specifically documented. In this case it works with the abstract class ItemField, but this may not always be the case.
The TOM.Net API only defines Definition and Name properties for ItemField, so you need to cast your ItemField object to something more specific.
the TextField abstract class, which SingleLineTextField inherits from, defines a ToString() method, but also Value and Values properties, which are much better suited to what you're trying to do. Looking at the documentation, we can see that Values will give us an IList<String> of the values, even if your field is not multi-valued. Perfect!
So, to answer your question, "I was looking for some way to find out if a SingleLineTextField has more values in it", you need to cast your ItemField as a TextField and check the number of Values it provides, thus:
TextField textField = (TextField)itemField;
// If you need to deal with multi-valued fields separately
if (textField.Values.Count > 1)
{
//Logic to deal with multiple values goes here
}
else
{
//Logic to deal with single valued goes here
}
// Much better... If you can deal with any number of values in a generic fashion
foreach (string value in textField.Values)
{
// Generic code goes here
}