List won't add string Array - c#

I created the following class:
class TrdRamValue
{
double Value = 0.0;
TrdState State = TrdState.Ok;
DateTime dt = DateTime.UtcNow;
}
I then created a list with this class to store the information:
List<TrdRamValue> DMSrows = new List<TrdRamValue> ();
And I use the following inside a Handler to constantly insert values every second:
string[] value = new string[3];
value[0] = val;
value[1] = val.Error.ToString ();
value[2] = val.Time.ToString ();
DMSrows.AddRange (value);
But in code it keeps saying that I have an error in my argument, that I can't convert string[] to System.Collections.Generic.IEnumerable.
I'm completely lost on this one...
ANSWER:
It was just a minor error from my part, and I also took huMpty duMpty suggestion since he's completely right, I don't need that string array.
All I had to do was make the class and the variables inside public in order to do what huMpty duMpty told me.
public class TrdRamValue
{
public double Value = 0.0;
public TrdState State = TrdState.Ok;
public DateTime dt = DateTime.UtcNow;
}
Then apply huMpty duMpty suggestion:
TrdRamValue value = new TrdRamValue() ;
value.Value = val;
if (!val.Error) {
value.State = TrdState.Ok;
}
else if (val.Error) value.State = TrdState.Error;
value.dt = val.Time;
DMSrows.Add (value);

Your List is not a List<string> but a List<TrdRamValue>. Therefore, you cannot add strings to the list. You can only add instances of TrdRamValue, or, in the case of AddRange, an IEnumerable (such as an array) of TrdRamValue.
So you can do this:
TrdRamValue toAdd = new TrdRamValue { Value = val, State = ..., dt = ... };
dmsRows.Add(toAdd);
(btw naming a variable DMSRows does not fit with the .net naming conventions).

You're trying to add strings to a list of TrdRamValue objects. Your list is type-safe, which means you are only allowed to add TrdRamValue objects to it.

Not sure why you need string array here.
Also you don't need List.AddRange here since you adding one item. You can use List.Add
DMSrows.Add(new TrdRamValue{
Value =val,
State =val.Error,
dt =val.Time
});

Related

How to Get Custom Field value acumatica

I'm new in developing acumatica I am stuck at getting the value of a custom TextEdit field that I created. I can get all of the built-in field value through this code
InventoryItem items = (InventoryItem)Base.Item.Cache.Current;
but I cannot get the one that I have created at acumatica customization
here is the field I want to get
https://i.stack.imgur.com/gPln4.png
I already tried
InventoryItem items = (InventoryItem)Base.ItemSettings.Cache.Current;
var shortdesc = items.UsrShortDescription;
But it's not working and does not show the value inside the textbox
thank you in advance for helping
InventoryItem items = (InventoryItem)Base.ItemSettings.Current;
var itemExt = PXCache<InventoryItem>.GetExtension<InventoryItemExt>(items);
var shortdesc = itemExt.UsrShortDescription;
Vardan showed one way, for completeness of picture want to show another as well:
InventoryItem items = (InventoryItem)Base.ItemSettings.Current;
var itemExt = items.GetExtension<InventoryItemExt>();
This is an example of getting value from a non-extension field. I did not use extension DAC to add the Gift card field to the store setup screen.
In a method I need to get the value of that field. I should check whether the order contains Gift card item or not.
public static bool GiftcardName(OrderModel orders, BZWoocommerceStore store)
{
// "ZGift CArd W" => "giftcard"
string wooCommName = string.Empty;
string wooCommNameNoSpases = string.Empty;
bool containsGiftcardName = false;
bool isGiftcard = false;
foreach (OrderLineModel line in orders.LineItems)
{
string gNameInAcumatica = store.GiftcardIdentifier;
string gNameInAcumaticaWithoutSpaces = gNameInAcumatica.Replace(" ", "");
wooCommName = line.Name; //pattern
wooCommNameNoSpases = wooCommName.Replace(" ", "");
//wooCommNameNoSpases = new string(wooCommName.ToCharArray()
// .Where(c => !Char.IsWhiteSpace(c))
// .ToArray());
//woCommNameNoUperCase= wooCommNameNoSpases.ToLower();
//isGiftcardName= woCommNameNoUperCase.Contains(gName);
//containsGiftcardName = wooCommNameNoSpases.Contains(gName);
containsGiftcardName = Regex.IsMatch(wooCommNameNoSpases, gNameInAcumaticaWithoutSpaces, RegexOptions.IgnoreCase);
if(containsGiftcardName)
{
isGiftcard = true;
}
}
return isGiftcard;
}
So, when I call this method I give to that 2 arguments, orders and store.
The store argument was created in this way.
public PXSelect<BZWoocommerceOrder> Order;
In an action method I wrote this.
string storeCode = this.Order.Current.StoreCode;
BZWoocommerceStore store = PXSelect<BZWoocommerceStore, Where<BZWoocommerceStore.storeCode, Equal<Required<BZWoocommerceStore.storeCode>>>>.Select(this, storeCode);
My GiftcardName() method sees the value of original field. Writing "Original" I mean that you do not use any technique like this one.
BZSOOrderExt rowExt = sender.GetExtension<BZSOOrderExt>(row);

Get specific values of a struct/List

I'm creating a game in Unity3D + C#.
What I've got at the moment: an SQL datatable, consisting of 8 columns holding a total of 3 entries and a list "_WeapList" that holds every entry (as shown below).
public struct data
{
public string Name;
public int ID, dmg, range, magazin, startammo;
public float tbtwb, rltimer;
}
List<data> _WeapList;
public Dictionary<int, data>_WeapoList; //probable change
[...]
//reading the SQL Table + parse it into a new List-entry
while (rdr.Read())
{
data itm = new data();
itm.Name = rdr["Name"].ToString();
itm.ID = int.Parse (rdr["ID"].ToString());
itm.dmg = int.Parse (rdr["dmg"].ToString());
itm.range = int.Parse (rdr["range"].ToString());
itm.magazin = int.Parse (rdr["magazin"].ToString());
itm.startammo = int.Parse (rdr["startammo"].ToString());
itm.tbtwb = float.Parse(rdr["tbtwb"].ToString());
itm.rltimer = float.Parse(rdr["rltimer"].ToString());
_WeapList.Add(itm);
_WeapoList.Add(itm.ID, itm);//probable change
}
Now I want to create a "Weapon"-Class that will have the same 8 fields, feeding them via a given ID
How do I extract the values of a specific item (determined by the int ID, which is always unique) in the list/struct?
public class Weapons : MonoBehaviour
{
public string _Name;
public int _ID, _dmg, _range, _magazin, _startammo;
public float _tbtwb, _rltimer;
void Start()
{//Heres the main problem
_Name = _WeapoList...?
_dmg = _WeapoList...?
}
}
If your collection of weapons may become quite large or you need to frequently look up weapons in it, I would suggest using a Dictionary instead of a List for this (using the weapon ID as the key). A lookup will be much quicker using a Dictionary key than searching through a List using a loop or LINQ.
You can do this by modifying your code to do this as follows:
public Dictionary<int, data>_WeapList;
[...]
//reading the SQL Table + parse it into a new List-entry
while (rdr.Read())
{
data itm = new data();
itm.Name = rdr["Name"].ToString();
itm.ID = int.Parse (rdr["ID"].ToString());
itm.dmg = int.Parse (rdr["dmg"].ToString());
itm.range = int.Parse (rdr["range"].ToString());
itm.magazin = int.Parse (rdr["magazin"].ToString());
itm.startammo = int.Parse (rdr["startammo"].ToString());
itm.tbtwb = float.Parse(rdr["tbtwb"].ToString());
itm.rltimer = float.Parse(rdr["rltimer"].ToString());
_WeapList.Add(itm.ID, itm);//probable change
}
Then, to access elements on the list, just use the syntax:
_WeapList[weaponID].dmg; // To access the damage of the weapon with the given weaponID
Guarding against invalid IDs:
If there's a risk of the weaponID supplied not existing, you can use the .ContainsKey() method to check for it first before trying to access its members:
if (_WeapList.ContainsKey(weaponID))
{
// Retrieve the weapon and access its members
}
else
{
// Weapon doesn't exist, default behaviour
}
Alternatively, if you're comfortable using out arguments, you can use .TryGetValue() instead for validation - this is even quicker than calling .ContainsKey() separately:
data weaponData;
if (_WeapList.TryGetValue(weaponID, out weaponData))
{
// weaponData is now populated with the weapon and you can access members on it
}
else
{
// Weapon doesn't exist, default behaviour
}
Hope this helps! Let me know if you have any questions.
Let specificWeapon be a weapon to be searched in the list, then you can use the following code to select that item from the list of weapons, if it is not found then nullwill be returned. Hope that this what you are looking for:
var selectedWeapon = WeapList.FirstOrDefault(x=> x.ID == specificWeapon.ID);
if(selectedWeapon != null)
{
// this is your weapon proceed
}
else
{
// not found your weapon
}
You can use LINQ to search specific object through weaponId
var Weapon = _WeapList.FirstOrDefault(w=> w.ID == weaponId);

C# variable assignment

Can someone show me a simple way to assign variables.
I have many variables and not really know how to do, whether it be possible to use a loop?`
public void SwappingPlaces1()
{
Section_1[0] = Receiver_1[0];
Section_1[1] = Receiver_2[0];
Section_1[2] = Receiver_3[0];
Section_1[3] = Receiver_4[0];
Section_1[4] = Receiver_5[0];
Section_1[5] = Receiver_6[0];
Section_1[6] = Receiver_7[0];
Section_1[7] = Receiver_8[0];
Section_1[8] = Receiver_9[0];
Section_1[9] = Receiver_10[0];
Section_1[10] = Receiver_11[0];
Section_1[11] = Receiver_12[0];
Section_1[12] = Receiver_13[0];
Section_1[13] = Receiver_14[0];
Section_1[14] = Receiver_15[0];
Section_1[15] = Receiver_16[0];
Section_1[16] = Receiver_17[0];
Section_1[17] = Receiver_18[0];
Section_1[18] = Receiver_19[0];
Section_1[19] = Receiver_20[0];
Section_1[n] = Receiver_n[0];
...
}
You need to use reflection to get the names of the properties/fields by their name. Assuming Reciever_n is a property:
var properties = this.GetType().GetProperties();
for(int i = 0; i < n; i++)
{
var p = properties.Single(x => x.Name == "Receiver_" + i);
var value = p.GetValue(this, new object[] { 0 });
}
First you get all the properties defined on the type. Now you loop your list and get that single property with the name Receiver_ plus the current index.
Finally you invoke that property on the instance and provide the index of the indexed property (which is equal to zero here).
EDIT: However having so many properties with equal name and type seems a design-flaw, you should consider your actual design.
Thus a better appraoch might be to have just one single two-dimensional array Receiver.
You could add reference variables to an array and iterate over them. This is mostly usefull, clearing gui controls, like textboxes/labels etc.
var variables = new[] { Receiver_1, Receiver_2, Receiver_3, Receiver_4,
Receiver_5, Receiver_6 };
for(int i=0; i<Section_1.Length;i++)
Section_1[i] = variables[i][0];
But an index out of bounds is easely created
You could also use reflection.

How can I determine if this method is threadsafe?

private void PerformValuations(DateTime testDate, RegressionEffectivenessTest.RegressionDateWithValues date)
{
var valueDate = new LegacyWCFRateTimeStamp { Type = RateTimeStampType.EndOfDay, TimeStamp = date.ValueDate };
var curveDate = new LegacyWCFRateTimeStamp { Type = RateTimeStampType.EndOfDay, TimeStamp = date.CurveDate };
var shiftDate = new LegacyWCFRateTimeStamp { Type = RateTimeStampType.EndOfDay, TimeStamp = date.ShiftDate };
if (date.NeedHedgeValues)
{
date.HedgeCleanPrice = 0M;
date.HedgeCleanIntrinsicValue = 0M;
foreach (var tran in _hedgeTranQuoteIds)
{
var tranquoteId = tran.TranQuoteId;
CheckAndLoadTrade(testDate, valueDate, shiftDate, curveDate, tran, tranquoteId);
var result = ValueTrade(tranquoteId);
var rtnVal = !result.Succeeded
? HandleFailure(tranquoteId, shiftDate, curveDate, result, valueDate)
: CreateAccountingValuation(valueDate, result);
date.HedgeCleanIntrinsicValue += rtnVal.IntrinsicValue - rtnVal.AccruedInterest.GetValueOrDefault(0);
date.HedgeCleanPrice += rtnVal.CleanPrice;
}
}
So I'm trying to run a Parallel.ForEach on this method. There were a couple of things that I was worried about. The first one is within the CheckAndLoadTrade method, it accesses a private Dictionary of the class to possibly add an item to it if it isn't there, and then the ValueTrade method gets an item from this dictionary.
If I parallel this out, am I going to run into any thread safety issues with the dictionary being accessed? Or possibly anything else I didn't notice? All other method calls use variables defined in their own scope, it's really just this one Dictionary that I am worried about. Should I throw a lock before and after the actual dictionary access happens?
What part are you trying to parallelize? The foreach loop?
If you can, use a ConcurrentDictionary. within CheckAndLoadTrade. Another concern is what code runs when the trade is not in the dictionary. Is the "loadtrade" code thread-safe?

C# Array Conversion

Any help here as I'm a C# noob. The following code works fine and returns 1 string ViewState2. I'd like it to return an array of ViewState2 and EventValidation2 so I can manipulate it later on. How would I convert the code below to return an array?
public string get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string ViewState2 = ViewState.Attributes[3].Value;
string EventValidation2 = EventValidation.Attributes[3].Value;
//Display the values
//System.Console.WriteLine(ViewState.Attributes[3].Value);
//System.Console.WriteLine(EventValidation.Attributes[3].Value);
//System.Console.ReadKey();
return ViewState2;
}
Don't use an array, but a class. Doing this, you don't have to remember what each element means.
public class Status
{
public string ViewState {get; set;}
public string EventValidation {get; set;}
}
using System;
using HtmlAgilityPack;
[...]
public Status GetStatus(string localFileName)
{
var dtsDoc = new HtmlDocument();
dtsDoc.Load(localFileName);
//Pull the values
var viewStateNode = dtsDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var eventValidationNode = dtsDoc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string viewState = viewStateNode.Attributes[3].Value;
string eventValidation = eventValidationNode.Attributes[3].Value;
//Display the values
//Console.WriteLine(viewState);
//Console.WriteLine(eventValidation);
//Console.ReadKey();
return new Status
{
ViewState = viewState,
EventValidation = eventValidation
}
}
Also, you should read up on coding guidelines and naming conventions in the C# language, also the using statement might be interesting. I have corrected some "mistakes", but probably didn't catch all. Also, I have renamed a couple of variables, to make their content clearer. You also might want to look into using the var keyword only in a loop, while using LINQ (or anomynous types in general) or with really long class names. Written out type names can increase readability quite a lot.
If you really want an array with ViewState2 and EventValidation2 in it, you can make the following changes:
// Notice: return value of string[] instead of string
public string[] get_status(string local_frame);
And:
// Notice: returning an array
return new string[] { ViewState2, EventValidation2 };
That said, this is really the "quick and dirty" approach, and is not really appropriate if you're going to want this code to be maintainable (when's the last time you read documentation on a function that "returns an array of length 2, with a string representing X as the first element and another string representing Y as the second"?).
Femaref's right; the correct thing to do would be to encapsulate the information you want returned in its own type.
Assuming you answer yes to this question (although I'd recommend a different approach, see below) this will do what you're asking:
public String[] get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
string ViewState2 = ViewState.Attributes[3].Value;
string EventValidation2 = EventValidation.Attributes[3].Value;
String[] retValues = new String[2];
retValues[0] = ViewState2;
retValues[1] = EventValidation2;
return retValues;
//Display the values
//System.Console.WriteLine(ViewState.Attributes[3].Value);
//System.Console.WriteLine(EventValidation.Attributes[3].Value);
//System.Console.ReadKey();
return ViewState2;
}
That said, I would follow the approach afte the line.
I'd write a class that has the data members you want:
public class DataClass
{
public string ViewState { get; set; }
public string EventValidation { get; set; }
}
Then I'd modify the method to return an instance of your data class.
public DataClass get_status(string local_fname)
{
var dts_doc = new HtmlAgilityPack.HtmlDocument();
dts_doc.Load(local_fname);
//Pull the values
var ViewState = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[1]/input[4]/#value[1]");
var EventValidation = dts_doc.DocumentNode.SelectSingleNode("/html[1]/body[1]/div[2]/input[1]/#value[1]");
var dc = new DataClass();
dc.ViewState = ViewState.Attributes[3].Value;
dc.EventValidation = EventValidation.Attributes[3].Value;
return dc;
}
string[] array = new string[2];
array[0] = ViewState2;
array[1] = EventValidation2;
return array;
But it seems to trivial as answer. Please Does it solve your problem? If no, can you specify better the question please?

Categories