I need to set a default value to a member class, this value can vary and it's set at the beginning of the execution; I have this so far, minScore is my default value
public class Zones : GeneralIndicator
{
public int IndicatorType { get; set; }
public string Code { get; set; }
public string Score { get; set; } //TODO: calcular desde aca el score usando el indicatortype
public double Latitude { get; set; }
public double Longitude { get; set; }
private int minScore = 0;
public void setMinScore(int value)
{
minScore = value;
}
}
I get the minScore value as a parameter when calling the application. What's the best way to set minScore for every object generated in runtime?
Two options:
Create a ZonesFactory class, which takes a defaultMinScore in the constructor (to remember) and has a CreateZones method which creates an instance and sets the min score:
public class ZonesFactory
{
private readonly int defaultMinScore;
public ZonesFactory(int defaultMinScore)
{
this.defaultMinScore = defaultMinScore;
}
public Zones CreateZones()
{
return new Zones(defaultMinScore);
}
}
Note that here I'm assuming you also create a new constructor for Zones which takes the minScore as a parameter. I suggest you get rid of the setMinScore method (which violates .NET naming conventions apart from anything else).
Use a static variable to keep the default, and set it in the Zones constructor
Personally I'd prefer the first of these.
Related
Please refer the below code
List<ProductDM> productDMList = _orderRepo.GetProductList(32, 12);
for (int i=0;i<productDMList.Count;i++)
{
productDMList[i].CabinetList[i].Min = productDMList[i].Min;
productDMList[i].CabinetList[i].Max = productDMList[i].Max;
}
public class ProductDM
{
public List<InventoryDM> CabinetList { get; set; }
public double Min { get; set; }
public double Max { get; set; }
}
public class InventoryDM
{
public Double Min { get; set; }
public Double Max { get; set; }
}
The requirement is to loop through the productDMList and bind the returned MIN and MAX values inside the cabinet list. ProductDM fills with MIN and MAX amounts but when assigning those to CabinetList, it returns an error.
This is because the CabinetList is initially empty and it doesn't show the MIN MAX properties in it.
I am using the above code to assign data but returns
Object reference not set to an instance of an object.
because of the CabinetList empty.
How to initialize the cabinet list here???
As Marco Forberg's answer states initializing the CabinetList in the constructor prevents the
Object reference not set to an instance of an object.
exception.
In addition to this, instead of assigning the Min and Max values via the index accessor:
productDMList[i].CabinetList[i].Min = productDMList[i].Min;
productDMList[i].CabinetList[i].Max = productDMList[i].Max;
You should use the Add() method of the List<> type:
productDMList[i].CabinetList.Add(new InventoryDM { Min = productDMList[i].Min, Max = productDMList[i].Max });
otherwise you will get an
ArgumentOutOfRangeException
because you try to access an item on the list which doesn't exist yet.
Depending on your requirements you could do something like this
public class ProductDM
{
public List<InventoryDM> CabinetList { get; private set; }
public double Min { get; set; }
public double Max { get; set; }
public ProductDM()
{
CabinetList = new List<InventoryDM>();
}
}
or if you get your CabinetList data from an external source, e.g. database:
public class ProductDM
{
private List<InventoryDM> _cabinetList = null;
public double Min { get; set; }
public double Max { get; set; }
public List<InventoryDM> CabinetList
{ get
{
if(_cabinetList == null)
{
_cabinetList = ... // retrieve data from external source
}
return _cabinetList;
}
}
}
The issue is not the emptiness of the CabinetList, instead the list of objects is null as you can see in the debugger.
In order to initialize the list you can refer to the answers of this post:
How to initialize a C# string list (List<string>) with many string values
Note that you don't have a list of string but a list of <InventoryBM> objects, but the concept is analogous.
I have a method as follows which gets data and stores them to specific variables. I also have two static variables that preserves their value if a condition is met. My question is how can I store this data in attributes in a specific class ?
Like for example, I have a class called UserDetails with attributes :
UserDetails class
public class UserDetails {
public static string RateCountry { get; set; }
public static string RateWeek { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Second Class
For now, its working like this. But I want to enhance it by making use of objects.
public static string RateCountry { get; private set; }
public static string RateWeek { get; private set; }
public ActionResult ShowList()
{
int start = Convert.ToInt32(Request["start"]);
int length = Convert.ToInt32(Request["length"]);
string name = Request["search[value]"];
string address = Request[("columns[3][search][value]")];
string rateType = Request[("columns[7][search][value]")];
if (string.IsNullOrEmpty(rateType)) // if null, reset the static variables to null
{
RateCountry = "";
RateWeek = "";
}
else
{
if (CheckDate(rateType)) // if contains date, assign to RateWeek
{
RateWeek = rateType;
}
else
{
RateCountry = rateType; // else if contains a string word, assing to ratecountry
}
}
var items = AssignDetails(start, length, name, address, RateWeek, RateCountry);
return items;
}
Then instead of passing several parameters like start, length, name etc. in the method AssignDetails, I can pass an object of the UserDetails class directly taking into consideration the static variables.
Can someone please help ?
Note: In C#, they are called properties not attributes. Attributes are a totally different thing.
What you want to do is straight forward:
Firstly, you need to change your method so it accepts your class UserDetails as an argument:
public void AssignDetails(UserDetails userDetails)
{
// Use userDetails here to do whatever you want
}
Secondly, when you call the above method, you need to pass the argument to it. You can create an instance of UserDetails and pass it to the AssignDetails method:
var userDetails = new UserDetails
{
Start = start,
Length = length,
Name = name
Address = address
}
I am not sure why RateWeek, and RateCountry properties are static in your class, but to set those you can do them as below (Please note it is using the class and not the instance of the class):
UserDetails.RateWeek = RateWeek;
You could make use of the instance's properties as an indirection to the class' static properties, although all this thing is really ugly in terms of design.
public class UserDetails
{
public static string PersistedRateCountry { get; set; }
public static string PersistedRateWeek { get; set; }
public static string RateCountry
{
get { return string.IsNullOrEmpty(rateType) ? "" : PersistedRateCountry; }
set { PersistedRateCountry = value; }
}
public static string RateWeek
{
get { return string.IsNullOrEmpty(rateType) ? "" : PersistedRateWeek; }
set { PersistedRateWeek= value; }
}
public static string RateWeek { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
I strongly suggest you to move these static properties out to another class, which would be responsible for persisting them.
E.g. try to separate your Data Object (which just holds data) from your Business Object (which contains business logic, and is constructed by receiving a Data Object as parameter). Put all that crazy persistence logic in the Business Object, and use the Business Object everywhere in your code (instead of using the Data Object).
Keep your classes short and clean. If you are coding a lot in the same class, it's probably because you got a bad object-oriented design.
This question is related to this question. I managed to get one step further, but I am now unable to initialize my whole object with default values in order to prevent it from being null at list level. The goal of this is to hand down the "null" values to my SQL query. Ultimately what I want is one record in my DB that will express: This row has been recorded, but the related values were "null".
I have tried Brian's fiddle and it does not seem to work for me to initialize the whole model with standard values.
Expectation: Upon object initialisation the "null" values should be used and then overwritten in case there is a value coming through JSON deserialisation.
Here is what I have tried. None of this will have the desired effect. I receive this error:
Application_Error: System.ArgumentNullException: Value cannot be null.
Every time I try to access one of the lists in the data model.
namespace Project.MyJob
{
public class JsonModel
{
public JsonModel()
{
Type_X type_x = new Type_X(); // This works fine.
List<Actions> action = new List<Actions>(); // This is never visible
/*in my object either before I initialise JObject or after. So whatever
gets initialised here never makes it to my object. Only Type_X appears
to be working as expected. */
action.Add(new Actions {number = "null", time = "null", station =
"null", unitState = "null"}) // This also does not prevent my
//JsonModel object from being null.
}
public string objectNumber { get; set; }
public string objectFamily { get; set; }
public string objectOrder { get; set; }
public string location { get; set; }
public string place { get; set; }
public string inventionTime { get; set; }
public string lastUpdate { get; set; }
public string condition { get; set; }
public Type_X Type_X { get; set; }
public List<Actions> actions { get; set; }
}
public class Actions
{
public Actions()
{
// None of this seems to play a role at inititialisation.
count = "null";
datetime = "null";
place = "null";
status = "null";
}
// public string count { get; set; } = "null"; should be the same as above
// but also does not do anything.
public string count { get; set; }
public string datetime { get; set; }
public string place { get; set; }
public string status { get; set; }
}
public class Type_X
{
public Type_X
{
partA = "null"; // This works.
}
public string partA { get; set; }
public string PartB { get; set; }
public string partC { get; set; }
public string partD { get; set; }
public string partE { get; set; }
}
}
This is how I now initialize the object based on Brian's answer.
JObject = JsonConvert.DeserializeObject< JsonModel >(json.ToString(), new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore});
When I try to iterate over Actions' content, it (logically) gives me above mentioned null error.
for (int i = 0, len = JObject.actions.Count(); i < len; i++)
My current understanding of constructor initialisations:
If I define values such as count = "null"; they should appear in any new object that is created.
If default values are present I would then also expect that a list that has items with default values (such as count for ex.) would be of Count() 1 and not null. How is that even possible?
This will get you out of your bind:
private List<Actions> _actions = new List<Actions>();
public List<Actions> actions { get => _actions; set => _actions = value ?? _actions; }
This causes trying to set actions to null to set it to the previous value, and it is initially not null so it can never be null.
I'm not absolutely sure I'm reading your question right, so here's the same fragment for partA:
private string _partA = "null";
public string partA { get => _partA; set => _partA = value ?? _partA; }
I have found that in some cases, initializing generic lists with their default constructor on your model increases ease of use. Otherwise you will always want to validate they are not null before applying any logic(even something as simple as checking list length). Especially if the entity is being hydrated outside of user code, i.e. database, webapi, etc...
One option is to break up your initialization into two parts. Part 1 being the basic initialization via default constructor, and part 2 being the rest of your hydration logic:
JObject = new List < YourModel >();
... < deserialization code here >
Alternatively you could do this in your deserialization code, but it would add a bit of complexity. Following this approach will allow you to clean up your code in other areas since each access will not need to be immediately proceeded by a null check.
My application's front end is a DataGrid whose contents are passed to an Excel-generating method.
The catch is that the DataGrid deals with 13 columns: 10 of them are fixed (i.e., passed to Excel) while each of the last 3 is optional.
public class GridModel
{
public string Item { get; set; }
public string ItemName { get; set; }
public double TotalHeight { get; set; }
public double AGLheight { get; set; }
public double Embedment { get; set; }
public string Shape { get; set; }
public double TipDiameter { get; set; }
public double BaseDiameter { get; set; }
public double Taper { get; set; }
public double ShearReaction { get; set; }
// The following are optional, in 8 combinations, from all present to all absent
public double Camber { get; set; }
public double Rake { get; set; }
public double Angle { get; set; }
}
Being a C# newbie, I am considering the different approaches.
How would you folks deal with this? The simplest idea that comes to mind is to add 3 flags to the model:
bool IsColumn1Present;
bool IsColumn2Present;
bool IsColumn3Present;
Another way would be to add a level to the hierarchy, so each of the 'special' columns contains its own embedded flag:
if (Camber.flag) add(Camber.value);
That said, I would like to have the ability to somehow remove those 3 properties, so any attempt to access them would result in an error or impossibility.
If such thing exists, I guess it would be called "Variant Properties".
TIA
Note: I have solved this already by the manipulation of the Visibility.Visible field at the GUI level. Gurus, however, tell us that this is a bad idea. Best practices dictate that this facility should be part of the Model.
You could use nullable properties:
public double? Camber { get; set; }
Then check them for a value in your business logic:
if (thing.Camber.HasValue)
{
DoSomething(thing.Camber.Value);
}
It sounds like this might be exactly what you're after, given your comment on "variant" properties.
More info: http://msdn.microsoft.com/en-us/library/1t3y8s4s.aspx
Update: If you need to switch them off application-wide (as per your comment), you could either avoid setting the value in the first place when it's not wanted (this would be preferable as this is, as far as I'm concerned, business logic and doesn't belong in your dumb model classes) or extend this with a custom accessor:
private double? _camber;
public double? Camber
{
get
{
return ModelSettings.CamberEnabled
? _camber
: null;
}
set;
}
Then have some static/constant property somewhere:
public static class ModelSettings
{
public const bool CamberEnabled = true;
}
If the number of columns is constant (meaning the user can't add 'custom' columns), I would suggest a bit-field enum value like so:
[Flags]
public enum ColumnFlags
{
None = 0,
Camber = 0x1,
Rake = 0x2,
Angle = 0x4,
// Other optional columns here, keep them powers of 2!
}
Then in your Model class, keep a value such as:
public ColumnFlags ColumnFlags { get; set; }
Then you can use...
if(model.ColumnFlags.HasFlag(ColumnFlags.Camber))
{
// Do something here...
}
if(model.ColumnFlags.HasFlag(ColumnFlags.Rake))
{
// Do something here...
}
EDIT: Alternatively, you can use the Nullable<T> types to specify a "missing" or "empty" value.
Let's assume we have a class called "Tag".
public class Tag
{
public string Name { get; private set; }
public string Description { get; private set; }
public Type Type { get; private set; }
public Tag(string name, string description, Type type)
{
this.Name = name;
this.Description = description;
this.Type = type;
}
}
An example of an instance of a Tag would be:
Tag weightTag = new Tag("Weight", "Weight of item in kg", typeof(double))
Next assume that I have another class which has a collection of these Tags which a value relevant to that object mapped to each individual tag in the collection.
public class Item
{
public string Id { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public Dictionary<Tag, object> Tags { get; private set; }
public Item(string name, string description)
{
this.Name = name;
this.Description = description;
this.Tags = new Dictionary<Tag, object>();
}
public void AddTag(Tag tag, object value)
{
Tags.Add(tag, value);
}
}
I like this method due to the fact that you can take some predefined tags from some where and then just assign a value.
Tag buildDateTag = TagProvider.GetByName("BuildDate");
Tag weightTag = TagProvider.GetByName("Weight");
item.AddTag(buildDateTag, new DateTime(2013,12,06);
item.AddTag(weightTag, 10.5);
The downside to this method is that there will be a lot of boxing/unboxing. For instance, if I have a collection of Item and I want to sum all the values of the tag corresponding to weight I'd have to do something like:
double totalWeight = 0d;
foreach (var item in items)
{
if (Tags.ContainsKey(weightTag))
{
totalWeight += (double)Tags[weightTag];
}
}
In this instance I happened to know that I'm going to cast to double so the only performance penalty was the unboxing. However there may be instances where I will need to get the type of the object from the Type member in the Tag object in order to figure out what the type of the value object is.
My question is do you think there is a better way to architect this in order to get rid of the need to rely on using objects and unboxing everything every time I want to use a value?
And although this should probably be a different question, in this usage should Tag be a struct rather than a class?
IMHO, you can use an interface that has some of the common properties for the objects that you are expecting to be as part of the objects that you can tag against.
In that case, you can accept any object that Implements your interface and hence, you will have a neat and a cleaner code
Sample :
class BuildDateTag : ITaggable
{
int id;
string name;
double weight;
}
this way, you can have the tags defined inside the Item class from
public Dictionary<Tag, object> Tags { get; private set; }
to public Dictionary<Tag,ITaggable> Tags{get;set;}
Consider this and post the queries and your feasibility w.r.to this suggestion