change the string of dictionary list value to running code - c#

Dictionary<string, string> RoleName = new Dictionary<string, string>();
RoleName.Add("Admin", "toolStripMenuItem1.Enabled=true");
RoleName.Add("Manager", "toolStripMenuItem2.Enabled = true");
RoleName.Add("usero","btn.Enabled=true" );
RoleName.Add("customer", "btnorder.Enabled = true");
var t = contains the list of roles of the user in Database
foreach (var itemList in RoleName)
{
foreach (var itemdbRole in t)
{
if (itemList.Key == itemdbRole.Name)
{
CSharpCodeProvider cs = new CSharpCodeProvider(new Dictionary<string, string>());
CompilerParameters parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" });
parameters.GenerateExecutable = true;
CompilerResults results = cs.CompileAssemblyFromSource(parameters, itemList.Value); }
}
}
In the above code I want to execute the "value" in the dictionary list if it satisfied the conditions, I had used that code but it doesn't work, if anyone have better solution, as I want to execute the string in the dictionary's value as code, another issue using two for statements I think it consume more time any better way to check if the value of one list exists in the another list
Thank you in advance

You could store controls instead of strings in the dictionary:
Dictionary<string, Component> RoleName = new Dictionary<string, Component>
{
{ "Admin", toolStripMenuItem1 },
{ "Manager", toolStripMenuItem2 },
{ "user", btn },
{ "customer", btnorder }
};
// Disable all controls from the dictionary
toolStripMenuItem1.Enabled = false;
toolStripMenuItem2.Enabled = false;
btn.Enabled = false;
btnorder.Enabled = false;
var rolesFromDB = "Admin,user";
foreach (var role in rolesFromDB.Split(','))
{
if (RoleName.TryGetValue(role, out var component))
{
switch (component)
{
case ToolStripItem tItem:
tItem.Enabled = true;
break;
case Control control:
control.Enabled = true;
break;
}
}
}
Since the ToolStripItem doesn't inherit Control, we have to store controls as a Component in the dictionary.

Related

How to use lastEvaluatedKey with .ScanAsync?

I want to paginate through records in a dynamo table using a lastEvaluatedKey. How can I use the scanfilter to use the lastEvaluatedKey to begin the next request at that given location?
public List<Record>? GetRecords(Request request)
{
// Define marker variable
Dictionary<string, AttributeValue> startKey = null!;
var records = new List<Record>();
do
{
// Issue request
Condition cond = new Condition();
cond.ComparisonOperator = "NULL";
cond.AttributeValueList = new List<AttributeValue>() { };
var scanFilter = new Dictionary<string, Condition>() { { "ExecutedTime", cond } };
var allEvents = client.ScanAsync("rRecords", scanFilter).Result; //Dictionary<string, Condition> scanFilter
// View all returned items
List<Dictionary<string, AttributeValue>> items = allEvents.Items;
foreach (Dictionary<string, AttributeValue> item in items)
{
//do stuff
}
// Set marker variable
startKey = allEvents.LastEvaluatedKey;
} while (startKey != null && startKey.Count != 0);
return scheduledEventRecords;
}
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html I have tried this approach but those APIs (.Scan on the AmazonDynamoDBClient) are not available the version AWSSDK 3.5.1.20 that I am currently using.

How can I use begins_with method on sort key using c# in DynamoDB

If I was to use the high level model, I might try something like this:
public async void GetBooksData()
{
GetItemRequest request = new GetItemRequest
{
TableName = "Customer",
Key = new Dictionary<string, AttributeValue>
{
{"UserName", new AttributeValue{S="a"} },
{"BookNum", new AttributeValue { S = starts_with(queryTerm)} }
}
};
try
{
var response = await client.GetItemAsync(request);
if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
{
if (response.Item.Count > 0)
{
foreach (var item in response.Item)
{
MessageBox.Show("Value : \n" + item.Value.S);
}
}
}
}
catch (InternalServerErrorException iee)
{
MessageBox.Show(iee);
}
}
I need to use the method 'begins_with' for getting 2 items what UserName is 'a' and the BookNum are book_1 and book_2. This is possible in the high level interface in Java. As an example as to what can be done on the range key in Java:
public List<Comment> allForItemWithMinRating(String itemId, int minRating) {
Comment comment = new Comment();
comment.setItemId(itemId);
Condition condition = new Condition()
.withComparisonOperator(ComparisonOperator.GE)
.withAttributeValueList(
new AttributeValue()
.withN(Integer.toString(minRating)));
DynamoDBQueryExpression<Comment> queryExpression
= new DynamoDBQueryExpression<Comment>()
.withHashKeyValues(comment)
.withRangeKeyCondition(
"rating",
condition
)
.withScanIndexForward(false);
return mapper.query(Comment.class, queryExpression);
}
In the low level interface for C# you can achieve this as so:
var requestDynamodb = new QueryRequest
{
TableName = "GroupEdEntries",
KeyConditionExpression = "partition_key = :s_Id and begins_with(sort_key, :sort)",
ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
{":s_Id", new AttributeValue { S = my_id }},
{":sort", new AttributeValue { S = sort_key_starts_with }}
},
ConsistentRead = true
};
var results = await client.QueryAsync(requestDynamodb);
where the keys are called partition_key and sort_key. However, this returns the results as attribute values, which then need to be converted into POCOs one property at a time. It requires using reflection and is made more complicated using converters. It seems strange that this fundamental functionality (as well as other functionality) isn't supported in the C# SDK.
I ended up using reflection to create the tables based on the attributes, when this is also supported by default in Java. Am I missing a high level API for C#?
It's a bit of a different syntax and I can't find it documented anywhere (other than in code comments), but this works for me:
string partition_key = "123";
string sort_key_starts_with = "#type"
List<object> queryVal = new List<object>();
queryVal.Add(sort_key_starts_with);
var myQuery = context.QueryAsync<GroupEdEntry>(partition_key, QueryOperator.BeginsWith, queryVal);
var queryResult = await myQuery.GetRemainingAsync();

Assigning values to array elements based on a look up table

HI i am writing a c# program where i need to populate a array based on a look up table and set of string arrays with metadata. My lookup table looks like this (Table with key: transmitter, value: Array of receiver)
{
LED1: ["px1","px2","px3"],
LED2: ["px4","px5","px6"]
}
and my meta arrays looks like this (It is dynamic. Just an example. This comes as a response from DB query.)
var transmitters = new string[] { "LED1", "LED2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
My requirement is
If the transmitter LED1 or LED2 (or any other transmitter) is present in the lookup table, the value of the transmitter (ie ["px1","px2","px3"]) has to be compared with the receiver which are present in the lookup and led has to be marked yellow.
Orphan tranmitter or/ receiver has to be marked red.
Example
LookUp
{
LED1: ["px1", "px2", "px3"],
LED2: ["px5", "px8"]
}
Tranmitters and receivers
var transmitters = new string[] { "led1", "led2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
the result should be a list as
led1-yellow
px1-yellow
px2-yellow
px3-yellow
led2-yellow
px5-yellow
px4-red
px6-red.
I have written code that works
public class Program
{
public static void Main()
{
var transmitters = new string[] { "led1", "led2" };
var receivers = new string[] { "px1", "px2", "px3", "px4", "px5", "px6" };
var lookup = new Dictionary<string, string[]>() { { "led1", new string[] { "px1", "px2", "px3" } }, { "led2", new string[] { "px5", "px8" } } };
var blocks = new List<Block>();
var blocksTracker = new List<string>();
foreach (var transmitter in transmitters)
{
if (lookup.ContainsKey(transmitter))
{
var receiverLookup = lookup[transmitter];
var intersection = receivers.Intersect(receiverLookup).ToArray();
if (intersection.Length > 0)
{
blocks.Add(new Block() { Id = transmitter, status = "yellow" });
blocksTracker.Add(transmitter);
foreach (var receiver in intersection)
{
blocks.Add(new Block() { Id = receiver, status = "yellow" });
blocksTracker.Add(receiver);
}
}
else
{
blocks.Add(new Block() { Id = transmitter, status = "red" });
blocksTracker.Add(transmitter);
}
}
}
}
}
I am new to c# and i wanted to know if there is a better way of doing this. Please help. You can see the working fiddle Here

Convert string to to HtmlTableRow Control

I have a HTML row (<tr>) generated on client side, I want to convert the string which contains the row-cells information in a HtmlTableRow control. That is what I have done so far using the example on Convert string to WebControls - asp.net. Thanks
string row = "<tr><td>item</td><td><input name=\"radio0\" type=\"radio\"/></td></tr>";
Dictionary<string, HtmlContainerControl> controlConstructor = new Dictionary<string, HtmlContainerControl>
{
{"tr", new HtmlTableRow()},
{"td", new HtmlTableCell()}
};
var htmlDoc = XElement.Parse(row);
Func<XElement, HtmlControl> constructHtmlStructure = null;
constructHtmlStructure = (o =>
{
var control = controlConstructor[o.Name.ToString()];
if (o.HasElements)
{
control.Controls.Add(constructHtmlStructure(o.Elements().Single())); //Exception: Sequence contains more than one element (When is a input item)
}
else
{
control.InnerText = o.Value;
}
return control;
});
HtmlTableRow structure = (HtmlTableRow)constructHtmlStructure(htmlDoc);
why don't you use much simpler ways to parse your string to HtmlTableRow.
your Dictionary<string, HtmlContainerControl> controlConstructor considers only tr and td, what about input control nested inside them?
so even if you get away through that "sequence contains more than one element", using a foreach loop, you will get an error "key doesn't exist".
and even if you manage overcome that(by adding input key in your dictionary), you cannot parse it to a HtmlContainerControl.
and even if you do, by updating your Dictionary<string, HtmlContainerControl> to Dictionary<string, HtmlControl> , you will have to think of ways to handle that input control because, for that you cannot do control.InnerText = o.value;
hence a much simpler way:
string row = "<tr><td>item</td><td><input name=\"radio0\" type=\"radio\"/></td></tr>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(row);
HtmlTableRow tblRow = new HtmlTableRow();
foreach (XmlNode node in doc.SelectSingleNode("tr").ChildNodes)
{
HtmlTableCell cell = new HtmlTableCell();
cell.InnerText = node.InnerXml;
foreach (XmlNode childNode in node.ChildNodes)
{
if (childNode.Name == "input")
{
if (childNode.Attributes["type"] != null)
{
switch (childNode.Attributes["type"].Value.ToString())
{
case "radio":
HtmlInputRadioButton rad = new HtmlInputRadioButton();
rad.Name = childNode.Attributes["name"].ToString();
cell.Controls.Add(rad);
break;
///other types of input controls
default:
break;
}
}
else
{
HtmlInputButton button = new HtmlInputButton("button");
cell.Controls.Add(button);
}
}
}
tblRow.Cells.Add(cell);
}
as you can see, it is a very rough and strict logic: what best you can do is to come up with a recursive function, to construct your HtmlTableRow
Linq's Single method returns the first and only element of a sequence - if there's more than one element it throws the exception you're seeing. As your table row contains two table cells, its o.Elements() method returns an enumerable with two members, and using Single makes it fall over.
Instead of using:
control.Controls.Add(constructHtmlStructure(o.Elements().Single()));
...use:
foreach(var element in o.Elements())
{
control.Controls.Add(constructHtmlStructure(element));
}
That way you iterate over each of the table row's cells, and add each one to the control.
Edit
There's another change you need to make. Your dictionary contains exactly one HtmlTableRow, and exactly one HtmlTableRow, both already created by the time you get into constructHtmlStructure. Instead of having pre-existing objects (and therefore only one instance of each available) you should have your dictionary create a new instance of each type on demand.
So instead of this (adjusted for spacing):
var controlConstructor = new Dictionary<string, HtmlContainerControl>
{
{ "tr", new HtmlTableRow() },
{ "td", new HtmlTableCell() }
};
...
var control = controlConstructor[o.Name.ToString()];
...try this:
var controlConstructor = new Dictionary<string, Func<XElement, HtmlControl>>
{
{ "tr", o => new HtmlTableRow() },
{ "td", o => new HtmlTableCell() }
};
...
var control = controlConstructor[o.Name.ToString()].Invoke(o);
You'll also need a function to create an input from an XElement, something like this:
private static HtmlControl CreateInputFromElement(XElement element)
{
// Create an appropriate HtmlInputControl...
}
...which you can add to your dictionary like this:
var controlConstructor = new Dictionary<string, Func<XElement, HtmlControl>>
{
{ "tr", o => new HtmlTableRow() },
{ "td", o => new HtmlTableCell() },
{ "input", CreateInputFromElement }
};

Adding properties of an Object together in a collection

I have an app that creates ContactList Objects and adds them to a Dictionary collection. My ContactList objects have a property called AggLabels which is a collection of AggregatedLabel objects containg Name and Count properties. What I am trying to do is change the "else" case of my code snippet so that before adding a new AggregatedLabel it will check whether the AggLabel.Name exists in the AggregatedLabel collection and if this is true it will not add the AggLabel.Name again. Instead it will add the value of AggLabel.Count (type int) to the existing AggregatedLabel object. So for an existing object, if the first Count value was 3 and the second value is 2 then the new Count value should be 5. In simple terms I want to have unique AggLabel Names and add together the Counts where the Names are the same. Hope that makes sense - would appreciate any help. Thanks!
Code snippet
Dictionary<int, ContactList> myContactDictionary = new Dictionary<int, ContactList>();
using (DB2DataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
int id = Convert.ToInt32(dr["CONTACT_LIST_ID"]);
if (!myContactDictionary.ContainsKey(id))
{
ContactList contactList = new ContactList();
contactList.ContactListID = id;
contactList.ContactListName = dr["CONTACT_LIST_NAME"].ToString();
//contactList.AggLabels = new ObservableCollection<AggregatedLabel>() { new AggregatedLabel() { Name = dr["LABEL_NAME"].ToString(), Count = Convert.ToInt32(dr["LABEL_COUNT"])}};
contactList.AggLabels = new ObservableCollection<AggregatedLabel>()
{
new AggregatedLabel()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
};
myContactDictionary.Add(id, contactList);
}
else
{
ContactList contactList = myContactDictionary[id];
contactList.AggLabels.Add(
new AggregatedLabel()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
}
}
There are two possible solutions I can think of:
1) Use a dictionary instead of the collection of aggregated labels the same way you do it for the contact dictionary. When yout use the name as key and the count as value, you can use the ContainsKey-Method to check whether the label already exists.
contactList.AggLabels = new Dictionary<string, int>();
...
else
{
ContactList contactList = myContactDictionary[id];
if (contactList.AggLabels.ContainsKey(dr["LABEL_NAME"].ToString()))
{
contactList.AggLabels[dr["LABEL_NAME"].ToString()] += Convert.ToInt32(dr["LABEL_COUNT"]);
}
else
{
contactList.AggLabels.Add(dr["LABEL_NAME"].ToString(), Convert.ToInt32(dr["LABEL_COUNT"]));
}
}
2) I you need to use the AggreagteLabel object you can use a loop to search throug all labels.
else
{
bool flagAggLabelFound = false;
ContactList contactList = myContactDictionary[id];
foreach(AggregateLabel aggLabel in contactList.AggLabels)
{
if(aggLabel.Name == dr["LABEL_NAME"].ToString())
{
aggLabel.Count += Convert.ToInt32(dr["LABEL_COUNT"]);
flagAggLabelFound = true;
break;
}
}
if (!flagAggLabelFound)
{
contactList.AggLabels.Add(
new AggregatedLabel()
{
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
}
I hope this helps.
I would try this:
ContactList contactList = myContactDictionary[id];
AggregateLabel existing = contactList.AggLabels.FirstOrDefault(
l => l.Name == dr["LABEL_NAME"].ToString()
);
if (existing == null) { contactList.AggLabels.Add(
new AggregatedLabel() {
Name = dr["LABEL_NAME"].ToString(),
Count = Convert.ToInt32(dr["LABEL_COUNT"])
}
);
}
else { existing.Count += Convert.ToInt32(dr["LABEL_COUNT"]); }
#extract these Aggregated Labels and put them in a separate Observable collection:
1) If you a Dictionary for storing the labels in the contact list, this should work:
ObservableCollection<AggregateLabel> copyOfAggregateLabels = new ObservableCollection<AggregateLabel>();
foreach (KeyValuePair<string, int> aggLabel in aggregateLabels)
{
copyOfAggregateLabels.Add(
new AggregatedLabel() {
Name = aggLabel.Key,
Count = aggLabel.Value
}
);
}
2) If you use an ObservableCollection of AggregateLabels, you get an AggregateLable instead of a KeyValuePair in the loop. The rest works the same way.
First I thought of something like:
ObservableCollection<AggregateLabel> copyOfAggregateLabels = new ObservableCollection<AggregateLabel>(aggregateLables);
But this way you get a new ObservableCollection, but the labels stored in the new collection are still referring to the same objects as the ones in the collection you copy.

Categories

Resources