I have a string variable which holds some value and I want to be able to check if that string exists in a dictionary as a key with its variable name.
For a clearer understanding as you can see in the following code;
string searchDuration = "200";
var response = new Dictionary<string, string>()
{
{"searchDuration","200"},
{"minRssi", "-70"},
{"optionalFilter","NO_FILTERS_ACTIVE_SCANNING"},
{"txPowerLevel","200"},
{"peripheralId","123wrong"}
};
I'm able to use ContainsKey method as following;
if (response.ContainsKey("searchDuration"))
if (searchDuration == pair.Value)
isEqual = true;
But I don't(actually can't) use it this way because;
I need to pass in every string variable dynamically, I can't write every variable name as a string to pass in to ConstainsKey method
It only check values and there might be multiple values with "200", this situation gives me false results.
I want to compare the value "200" only with related key which is "searchDuration", not with "txPowerLevel" which has the same value.
Is there a way to check whether a string variable exists as a key in a dictionary to compare it's value with dictionary members?
I'd suggest this approach:
string searchDuration = "200";
var response = new Dictionary<string, string>()
{
{"searchDuration","200"},
{"minRssi", "-70"},
{"optionalFilter","NO_FILTERS_ACTIVE_SCANNING"},
{"txPowerLevel","-16"},
{"peripheralId","123wrong"}
};
var wasItThere = response.TryGetValue(nameof(searchDuration), out var value);
Console.WriteLine(wasItThere && (value == searchDuration));
TryGetValue is better than ContainsKey since it gets the value at the same time as checking whether the key is there.
nameof is used to convert the variable name to its string representation.
I have explicitly not used pair.Value since that code in your original question strongly implies you are iterating through the Dictionary. This is not a good idea (performance wise).
If the variables you want to compare are all part of an object, then you can inspect that object with reflection and compare what is found inside the object with what is present in the Dictionary. Here is how:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var obj = new { searchDuration = "200", txPowerLevel = "100", other = "123"};
var stringProperties = obj
.GetType()
.GetProperties()
.Where(pi => pi.PropertyType == typeof(string) && pi.GetGetMethod() != null)
.Select(pi => new
{
Name = pi.Name,
Value = pi.GetGetMethod().Invoke(obj, null)}
)
.ToList();
var response = new Dictionary<string, string>()
{
{"searchDuration","200"},
{"minRssi", "-70"},
{"optionalFilter","NO_FILTERS_ACTIVE_SCANNING"},
{"txPowerLevel","200"},
{"peripheralId","123wrong"}
};
foreach (var item in stringProperties)
{
string v;
response.TryGetValue(item.Name, out v);
Console.WriteLine(item.Name + ": obj value=" + item.Value + ", response value=" + (v ?? "--N/A--"));
}
}
}
Working Fiddle: https://dotnetfiddle.net/gUNbRq
If the items are present as local variables then it can probably also be done (e.g. see here), but I would recommend putting it in object to keep the values you want to inspect separate from other variables that your method needs and uses.
Related
I have below Code :
ProductDto newProduct = new ProductDto() { Id = 2, Name = "Pixel xl",Price = 2000};
Then I serialize by below code and save it in database:
private static string ToJson(object model)
{
JsonSerializerSettings jsonWriter = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
};
var type = model.GetType();
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (PropertyInfo item in type.GetProperties())
{
var propName = item.Name;
var propValue = item.GetValue(model);
if (propValue == null) continue;
propValue = JsonConvert.SerializeObject(propValue, Formatting.Indented, jsonWriter);
dic.Add(propName, propValue.ToString());
}
return JsonConvert.SerializeObject(dic);
}
The result in database is like below :
{"Id":"2","Name":"\"Pixel xl\"","Price":"2000"}
so when I read that string and Desialize it I have below value for Name :
\"Pixel xl\" Instead : Pixel xl
I want to compare those like this but beceasue of "\ they are not same.
// newValue is "Pixel xl";
// oldValue is "\"Pixel xl\"";
if (!Object.Equals(newValue, oldValue))// this line always return true
{
// do somethid if they are not same
}
First:
It seems that you are using wrong comparison expression. By using Object.Equal you are telling that newValue and oldValue has the same object. They have the same "values" but not same "object".
MSDN:
If the current instance is a reference type, the Equals(Object) method
tests for reference equality, and a call to the Equals(Object) method
is equivalent to a call to the ReferenceEquals method. Reference
equality means that the object variables that are compared refer to
the same object.
Second:
The converted value has an extra double qoute \". You can manually removed that by using .Replace("\"", ""). You might want to create another comparison expression to compare your values.
Something like:
if (newValue.Name == oldValue.Name && newValue.Id == oldValue.Id && newValue.Price == oldValue.Price)
{
Console.WriteLine("Same");
}
else
{
Console.WriteLine("Not Same");
}
Sample code:
https://dotnetfiddle.net/mJgRsL
A side note:
You can refer to this link for the difference of Value vs Reference type object.
https://msdn.microsoft.com/en-us/library/4d43ts61(v=vs.90).aspx
In my desktop C# application I start with a dictionary. I want to be able to check this dictionary for a key. If the dictionary has this key, I would like to pass it on to a method. If the dictionary doesn't have this key, I would like to create a blank list and just pass that on instead. How can I do this?
I get the error "given key was not present in the dictionary". Can I add a default so it is never null maybe?
// myDic was declared as a Dictionary<string, List<string>
// Here is how I call someFunction
string text = SomeFunction(stringValue1, stringValue2, myDic[field1.field2]);
// SomeFunction looks like this
string SomeFunction (string string1, string string2, List<string> ra)
{
// method
return stringResult;
}
Updated based on comments. To pass one key that may or may not exist you may do this(assuming the value is a List):
// assuming the method we are calling is defined like this:
// public String SomeFunction(string string1, String string2, List<String> ra)
List<string> valueToPassOn;
if (_ra.ContainsKey(lc.Lc))
{
valueToPassOn = _ra[lc.Lc]
}
else
{
valueToPassOn = new List<string>();
}
string text = tooltip.SomeFunction(something1, something2, valueToPassOn);
Should you want to pass an entire dictionary (as the question originally read), regardless of whether or not the dictionary exists:
You have two options. Either create the dictionary regardless like this:
if (myDic == null)
{
// change var and var2 to the types of variable they should be, ex:
myDic = new Dictionary<string, List<string>>();
}
string text = SomeFunction(stringValue1, stringValue2, myDic);
or, what is probably the better option, in the declaration of the function SomeFunction add a dictionary as a variable with a default parameter. Just be sure that your function knows what to do if the dictionary is null.
string SomeFunction(string string1, string string2, Dictionary dictionary = null)
{
// method here
}
You can check if the key exists using ContainsKey method and if it returns false you can pass a default value you want:
// replace default(string) with the value you want to pass
// if the key doesn't exist
var value = myDic.ContainsKey(field1.field2) ? myDic[field1.field2] : default(string);
string text = SomeFunction(stringValue1, stringValue2, value);
What you need to do is make sure the dictionary actually contains the given key in the dictionary.
If you need to extract the value by key, use TryGetValue method:
string value;
if (myDict.TryGetValue(key, out value))
{
// Key exists in the dictionary, do something with value.
}
Use one of the following snippets in order to check if dictionary is empty and take some action:
var x = new Dictionary<string, string>();
if (x.Any())
{
//....
}
if (x.ContainsKey("my key"))
{
}
if (x.ContainsValue("my value"))
{
}
if (x.Count > 0)
{
}
In this function I load a template using Word and replace certain words with other words. That's not important. How do I change the function to use dynamic? In particular, how do I use the Enums (such as WdReplace.wdReplaceOne) without having a reference to Microsoft.Office.Interop.Word?
public static void CreateSheetByReplacement(String student, List<String> words)
{
Application WordApp = new Application();
WordApp.Documents.Add(Environment.CurrentDirectory + "\\SpellingsReplace.dot");
WordApp.Selection.Find.Execute(FindText: "studentname", Replace: WdReplace.wdReplaceOne, Wrap: WdFindWrap.wdFindContinue, ReplaceWith: student);
for (int i = 0; i < 80; i++)
{
String word = (i < words.Count ? words[i] : "");
WordApp.Selection.Find.Execute(FindText: "[word" + (i + 1) + "]", Replace: WdReplace.wdReplaceOne, Wrap: WdFindWrap.wdFindContinue, ReplaceWith: word);
}
WordApp.Visible = true;
WordApp = null;
}
I just need one example of how to use the enums.
While there is no way to easily use enums with such dynamic late binding other than by directly using respective Integer values, you can use some reflection and ExpandoObject to build dynamic lookup object:
public static class DynamicInterop
{
public static DynamicInterop()
{
var enumsDict = new ExpandoObject() as IDictionary<string, Object>;
// Get all enum types from interop assembly
var interopEnums = GetInteropAssembly()
.GetTypes()
.Where(type =>
typeof(Enum).IsAssignableFrom(type));
// For all enum types create a member in the enums dynamic object
foreach (var type in interopEnums)
{
var curEnum = new ExpandoObject() as IDictionary<string, Object>;
// Get Enum value name and values as KeyValuePairs
var enumKeyValues = Enum
.GetNames(type)
.Zip(Enum.GetValues(type).Cast<Object>(),
(key, value) =>
new KeyValuePair<String, Object>(key, value));
// Create members for every enum value name-value pair
foreach (var keyValue in enumKeyValues)
{
curEnum.Add(keyValue.Key, keyValue.Value);
}
enumsDict.Add(type.Name, curEnum);
}
DynamicInterop.Enums = enumsDict;
}
public static dynamic CreateWordApp()
{
throw new NotImplementedException();
}
public static dynamic Enums
{
get;
private set;
}
}
While such approach may not exactly suit your needs it will at least reduce the probability of passing wrong enum value.
P.S.: It is not tested, so there are may be few typos or other errors.
P.S.1: Still, with no Intellisense and other IDE and compiler assistance late binding to Interop with dynamic can easily become the most difficult part of the code to maintain.
var myObject = new { Id = 0, Name = "Test" };
I would like to get key name into variable in other part of project for ex.:
var keyName = someObject[0]; //someObject is passed myObject;
var value = someObject[1];
//Output keyName = Id; value = 0;
I know that dictionary would be good, but I have to stick to the delaration of myObject;
You can access the properties of your object this way:
myObject.GetType().GetProperties()
and the names e.g.
myObject.GetType().GetProperties()[0].Name //("Id")
It is not possible to do this with reflection, because variables won't have a name once compiled to IL. However, you can use expression trees and promote the variable to a closure:
static string GetVariableName<T>(Expression<Func<T>> expr)
{
var body = (MemberExpression)expr.Body;
return body.Member.Name;
}
You can use this method as follows:
static void Main()
{
var someVar = 3;
Console.Write(GetVariableName(() => someVar));
}
Note that this is pretty slow, so don't use it in performance critical paths of your application.
For a more complete example, see here.
I have a database object (a row), that has lots of properties (columns) that map to form fields (asp:textbox, asp:dropdownlist etc). I would like to transform this object and properties into a dictionary map to make it easier to iterate.
Example:
Dictionary<string, string> FD = new Dictionary<string,string>();
FD["name"] = data.name;
FD["age"] = data.age;
FD["occupation"] = data.occupation;
FD["email"] = data.email;
..........
How would I do this easily, without manually typing out all the various 100s of properties?
Note: FD dictionary indices are same as database column names.
Assuming that data is some object and that you want to put its public properties into a Dictionary then you could try:
Original - here for historical reasons (2012):
Dictionary<string, string> FD = (from x in data.GetType().GetProperties() select x)
.ToDictionary (x => x.Name, x => (x.GetGetMethod().Invoke (data, null) == null ? "" : x.GetGetMethod().Invoke (data, null).ToString()));
Updated (2017):
Dictionary<string, string> dictionary = data.GetType().GetProperties()
.ToDictionary(x => x.Name, x => x.GetValue(data)?.ToString() ?? "");
The HtmlHelper class allows a conversion of Anonymouns Object to RouteValueDictonary and I suppose you could use a .ToString() on each value to get the string repersentation:
var linkAttributes = System.Web.Mvc.HtmlHelper.AnonymousObjectToHtmlAttributes(linkHtmlAttributes);
The down side is this is part of the ASP.NET MVC Framework. Using a .NET Reflector, the code inside of the method is as follows:
public static RouteValueDictionary AnonymousObjectToHtmlAttributes(object htmlAttributes)
{
RouteValueDictionary dictionary = new RouteValueDictionary();
if (htmlAttributes != null)
{
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(htmlAttributes))
{
dictionary.Add(descriptor.Name.Replace('_', '-'), descriptor.GetValue(htmlAttributes));
}
}
return dictionary;
}
You'll see that this code is identical to the answer Yahia gave you, and his answer provides a Dictonary<string,string>. With the reflected code I gave you you could easily convert a RouteValueDictionary to Dictonary<string,string> but Yahia's answer is a one liner.
EDIT - I've added the code for what could be a method to do your conversion:
EDIT 2 - I've added null checking to the code and used String.Format for the string value
public static Dictionary<string, string> ObjectToDictionary(object value)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
if (value != null)
{
foreach (System.ComponentModel.PropertyDescriptor descriptor in System.ComponentModel.TypeDescriptor.GetProperties(value))
{
if(descriptor != null && descriptor.Name != null)
{
object propValue = descriptor.GetValue(value);
if(propValue != null)
dictionary.Add(descriptor.Name,String.Format("{0}",propValue));
}
}
return dictionary;
}
And to go from a Dictionary to an object check http://automapper.org/ which was suggested in this thread
Convert dictionary to anonymous object
var myDict = myObj.ToDictionary(); //returns all public fields & properties
.
public static class MyExtensions
{
public static Dictionary<string, object> ToDictionary(this object myObj)
{
return myObj.GetType()
.GetProperties()
.Select(pi => new { Name = pi.Name, Value = pi.GetValue(myObj, null) })
.Union(
myObj.GetType()
.GetFields()
.Select(fi => new { Name = fi.Name, Value = fi.GetValue(myObj) })
)
.ToDictionary(ks => ks.Name, vs => vs.Value);
}
}
Take a look at System.ComponentModel.TypeDescriptor.GetProperties( ... ). This is the way the normal data binding bits work. It will use reflection and return you a collection of property descriptors (which you can use to get the values). You can customize these descriptors for performace by implementing ICustomTypeDescriptor .