Creating a dictionary of any object - c#

What I want is the ability to store name,object pairs.
Unlike objC c#'s Dictionary requires types. In objC I would use id to mean "any object".
How would I manage this in c#.
So what I'm looking for is:
Dictionary<String,id>.
Sorry if this is really basic!

Without going into a lot of faffery to talk to multiple strongly typed lists of objects, the simplest way to achieve this is with a Dictionary<string, object> and to cast out your object type as you need it:
int i = (int)myDictionary["Age"];
string n = (string)myDictionary["Name"];
There are a few dynamic options here such as ExpandoObject:
http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
If you go the object dictionary approach, pay attention to boxing on value types. Using the dynamic approach won't have the boxing implications, but will require runtime resolution, so performance again is slightly impacted.
Nothing comes for free, but by and large you shouldn't see the effects of this minor overhead.

There's always the new dynamic type in .NET 4 if unboxing is an issue.

Not sure if I understood you correctly but you can make the following:
Dictionary s = new Dictionary();
Object a = new Int32();
a = 1;
Object b = new Double();
b = 2.0;
s.Add("a", a);
s.Add("b", b);
Int32 v = Convert.ToInt32(s["a"]);
Double u = Convert.ToDouble(s["b"]);
Console.WriteLine(v + " " + u);

Asking this may indicate there could be some bad design hidden behind this. It always does when you need a collection of heterogenous objects.
Because of not knowing the type of objects you have in the collection, you always need to do some kind of type checking, such as if (dictionary["xy"] is string) {...} which is a code smell.
Would some kind of wrapping into a common class be an option? That would allow you to specify some common operations on it (because you probably need some common operations if you need it to be in the same dict). For example something like (consider it as pseudocode):
class Base
{
bool IsCollection;
}
class StringItem : Base
{
string Contents;
IsCollection = false;
override ToString() { return this.Contents; }
}
class ListItem : Base
{
List<StringItem> Contents;
IsCollection = true;
override ToString() { return string.Join(",", this.Contents.ToArray() }
}
Then you could have a Dictionary<string, Base> and use operations defined on Base such as ToString or any custom.

Related

Access object property in array

class Program{
static void Main(string[] args){
object[] array = new object[1];
CreateItem item = new CreateItem();
item.name = "Necklace";
item.value = 5;
array[0] = item;
Console.WriteLine(array[0].name); //This part of the code doesn't work.
//It can't find the property name.
Console.ReadLine();
}
}
public class CreateItem {
public string name;
public int value;
}
Hi there! First of all I'd like to say that I'm not very familiar with objects, so excuse any mistakes you can see in the code (Although feel free to correct them, it'd be a great way to learn).
I've been working on making a small game using C#, but I came across a problem: I can't access my object properties when I put them in an array. Does anyone know which code I should use to be able to access my object properties while they're in an array?
Thanks for reading, and once again, excuse any silly mistakes I made, I'm fairly new to working with objects.
You shouldn't use an object array when you have a strong type that you're interested in using (and you know the type already).
CreateItem[] array = new CreateItem[1];
CreateItem item = new CreateItem();
item.name = "Necklace";
item.value = 5;
array[0] = item;
Console.WriteLine(array[0].name);
Necklace will now be outputted as expected.
You should probably look at using Generics and Lists, it is a very common and a valuable concept to grasp, as is the concept of Boxing and Unboxing which Generics solves.
class Program{
static void Main(string[] args){
List<CreateItem> list = new List<CreateItem>();
CreateItem item = new CreateItem();
item.name = "Necklace";
item.value = 5;
list.Add( item );
Console.WriteLine(list[0].name); //This part of the code doesn't work.
//It can't find the property name.
Console.ReadLine();
}
}
You could cast the object to your type, i.e.:
Console.WriteLine(((CreateItem)array[0]).name);
or (more effectively)
define your array as CreateItem[] array = new CreateItem[1];
Line
object[] array = new object[1];
creates an array of elements of type Object which is the base class for all other classes in .NET.
When you do:
array[n] = item;
an implicit conversion to the base type occurs and through array[n] you can access only members of the Object type portion of the CreateItem object (like ToString() or GetType() - their overrides will be called).
If you want to access entire CreateItem object, you have to cast the reference to the base type back to the original type, by using cast operator for example:
var name = ((CreateItem)array[0]).name;
This explicit casting is error-prone, has a run-time overhead and it is a sign of the poor design. When you know the type of the collection in advance, declare the collection of that type as other answers are suggesting:
// you can use array if you know number of items in advance and that number of elements will not change
CreateItem[] array = new CreateItem[N];
// use list if number of elements might change
List<CreateItem> list = new List<CreateItem>();

Comparing two objects' properties simply in c#

I have a class with lots of properties. A shallow copy is enough to fully replicate the object.
I need to compare an object just to check if it contains exactly the same values as another.
My ideas:
The first and most obvious solution is just to create a huge method block that compares each property, one after the other.
The second would be to serialize each object and hash the file or do some sort of md5 checksum on it. (Would this actually work?)
The third is to do some sort of reflection on the object, which would automate the first option, but create an added level of complexity.
Speed isn't really an issue.
I'm interested to hear thoughts, or any other methods I am missing to do such a thing.
Edit:
Thanks all. My solution (Modified to now be recursive on generic items):
public static bool IsSame<T>(T objA, T objB)
{
var type = typeof(T);
var properties = type.GetProperties();
foreach (var pi in properties.Where(a => a.CanRead))
{
if (pi.Name == "Item")
{
var piCount = properties.FirstOrDefault(a => a.Name == "Count");
int count = -1;
if (piCount != null && piCount.PropertyType == typeof(System.Int32))
count = (int)piCount.GetValue(objA, null);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
dynamic child1 = pi.GetValue(objA, new object[] { i });
dynamic child2 = pi.GetValue(objB, new object[] { i });
return IsSame(child1, child2);
}
}
}
else
{
var val1 = type.GetProperty(pi.Name).GetValue(objA, null);
var val2 = type.GetProperty(pi.Name).GetValue(objB, null);
if (val1 != val2 && (val1 == null || !val1.Equals(val2)))
return false;
}
}
return true;
}
Most serializers are designed to ensure that data retains its integrity during serialization and deserialization, not to produce a consistent serialized format. I would avoid using serialization for this purpose.
You may consider implementing IEquatable, to have each instance capable of comparing itself with instances of the same type. Or a class do do the comparisons for you that implements IEqualityComparer. How they do this comparison may be the 'big method' that compares properties one after the other, or uses reflection.
Reflection can be a fairly quick and simple way to achieve your goal but can cause problems down the line (for example if someone adds a property to your type that should not be included for comparing equality), but obviously the converse is also true (someone adds a property that should be checked for equality, but the equality comparison isn't updated). Which approach you use should generally be decided by how comfortable the team is with each approach in tandem with the context in which the class will be used.
In your case I'd probably recommend using the reflection based approach since you wish to check the result of a shallow clone operation, so all properties should be equal.
As an aside, I'd recommend using the MemberwiseClone method to create the clone, which would lessen the need for such stringent tests.
The third option (reflection) would be the slowest, but it would also be the most robust/testable.
The hash code would be very similar to the first option, since you would have to call all of your member variables, so 1 and 2 would require you to update your .Equals(obj) and .GenerateHash() methods every time you modify your member variable lists.
Here is some code to get you started:
foreach (FieldInfo field in this.GetType().GetFields())
{
if (o[field.Name] == null)
{
if (!field.GetValue(this).Equals(o[field.Name]))
return false;
}
else
{
return false;
}
}
return true;
Another thought is that if the properties return simple value types you could group them into immutable value types of their own. For instance, if you have a customer with properties string Address1 string Address2 string City string State string Zip, you could create a value type Address that implements its own equality comparer and use that.
Not sure if this applies to your situation, but I've found that when I have a class with a lot of properties, it is often possible to do this, and it tends to make my classes simpler and easier to reason about.
If you serialize you have to specify the serialization order on each Field/Property to ensure that all data is serialized int the same order. But all you would achieve is to implement GetHashCode() in an external class.
GetHashCode() has some examples on how to override it, so look there first.
If your class has a lot of fields, and you don't want to write all the code by hand. You could use reflection to autogenerate the code. If your class changes from time to time then you could create a partial class with the GetHashCode() implementation in a T4 template.

Converting a KeyValuePair collection in to anonymous type

Is it possible to convert a a IEnumerable<KeyValuePair<string,string>> of KeyValuePair to an anonymous type?
Dictionary<string, string> dict= new Dictionary<string, string>();
dict.add("first", "hello");
dict.add("second", "world");
var anonType = new{dict.Keys[0] = dict[0], dict.Keys[1] = dict[1]};
Console.WriteLine(anonType.first);
Console.WriteLine(anonType.second);
********************output*****************
hello
world
The reason i would like to do this is because I am retrieving an object from a webservice that represents an object that does not exist in the wsdl. The returned object only contains a KeyValuePair collection that contains the custom fields and their values. These custom fields can be named anything, so i cant really map an xml deserialization method to the final object i will be using (whose properties must be bound to a grid).
*Just because I used Dictionary<string,string> does not mean it is absolutely a dictionary, i just used it for illustration. Really its an IEnumerable<KeyValuePair<string,string>>
Ive been trying to thing of a way to do this, but am drawing a blank. This is c# .NET 4.0.
You could use the ExpandoObject, it is based on a dictionary.
I think there are a lot of ways to achieve this, but actually converting it in the same Dictionary seems a bit odd to do.
One way to accomplish this, by not actually converting everyting is the following:
public class MyDictionary<T,K> : Dictionary<string,string> // T and K is your own type
{
public override bool TryGetValue(T key, out K value)
{
string theValue = null;
// magic conversion of T to a string here
base.TryGetValue(theConvertedOfjectOfTypeT, out theValue);
// Do some magic conversion here to make it a K, instead of a string here
return theConvertedObjectOfTypeK;
}
}
ExpandoObject is the best option, which I believe is a wrapper around some XML. You could also use an XElement:
var result = new XElement("root");
result.Add(new XElement("first", "hello"));
result.Add(new XElement("second", "world"));
Console.WriteLine(result.Element("first").Value);
Console.WriteLine(result.Element("second").Value);
foreach (var element in result.Elements())
Console.WriteLine(element.Name + ": " + element.Value);
I haven't used ExpandoObject, so I'd try that first because I understand it does exactly what you want and is also something new and interesting to learn.

How do I reflect over the members of dynamic object?

I need to get a dictionary of properties and their values from an object declared with the dynamic keyword in .NET 4? It seems using reflection for this will not work.
Example:
dynamic s = new ExpandoObject();
s.Path = "/Home";
s.Name = "Home";
// How do I enumerate the Path and Name properties and get their values?
IDictionary<string, object> propertyValues = ???
In the case of ExpandoObject, the ExpandoObject class actually implements IDictionary<string, object> for its properties, so the solution is as trivial as casting:
IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;
Note that this will not work for general dynamic objects. In these cases you will need to drop down to the DLR via IDynamicMetaObjectProvider.
There are several scenarios to consider.
First of all, you need to check the type of your object. You can simply call GetType() for this.
If the type does not implement IDynamicMetaObjectProvider, then you can use reflection same as for any other object. Something like:
var propertyInfo = test.GetType().GetProperties();
However, for IDynamicMetaObjectProvider implementations, the simple reflection doesn't work. Basically, you need to know more about this object. If it is ExpandoObject (which is one of the IDynamicMetaObjectProvider implementations), you can use the answer provided by itowlson. ExpandoObject stores its properties in a dictionary and you can simply cast your dynamic object to a dictionary.
If it's DynamicObject (another IDynamicMetaObjectProvider implementation), then you need to use whatever methods this DynamicObject exposes. DynamicObject isn't required to actually "store" its list of properties anywhere. For example, it might do something like this (I'm reusing an example from my blog post):
public class SampleObject : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = binder.Name;
return true;
}
}
In this case, whenever you try to access a property (with any given name), the object simply returns the name of the property as a string.
dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".
So, you don't have anything to reflect over - this object doesn't have any properties, and at the same time all valid property names will work.
I'd say for IDynamicMetaObjectProvider implementations, you need to filter on known implementations where you can get a list of properties, such as ExpandoObject, and ignore (or throw an exception) for the rest.
If the IDynamicMetaObjectProvider can provide the dynamic member names, you can get them. See GetMemberNames implementation in the apache licensed PCL library Dynamitey (which can be found in nuget), it works for ExpandoObjects and DynamicObjects that implement GetDynamicMemberNames and any other IDynamicMetaObjectProvider who provides a meta object with an implementation of GetDynamicMemberNames without custom testing beyond is IDynamicMetaObjectProvider.
After getting the member names it's a little more work to get the value the right way, but Impromptu does this but it's harder to point to just the interesting bits and have it make sense. Here's the documentation and it is equal or faster than reflection, however, unlikely to be faster than a dictionary lookup for expando, but it works for any object, expando, dynamic or original - you name it.
Requires Newtonsoft Json.Net
A little late, but I came up with this. It gives you just the keys and then you can use those on the dynamic:
public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
{
JObject attributesAsJObject = dynamicToGetPropertiesFor;
Dictionary<string, object> values = attributesAsJObject.ToObject<Dictionary<string, object>>();
List<string> toReturn = new List<string>();
foreach (string key in values.Keys)
{
toReturn.Add(key);
}
return toReturn;
}
Then you simply foreach like this:
foreach(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor))
{
dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName];
// And
dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value
}
Choosing to get the value as a string or some other object, or do another dynamic and use the lookup again.
Simple solution to only reflect over json objects:
using System.Collections.Generic;
using System.Text.Json;
dynamic d = new {a = 1, b = 2, c = 3};
foreach ((string k, object o) in JsonSerializer.Deserialize<Dictionary<string, object>>(JsonSerializer.Serialize(d)))
{
}

Can you Instantiate an Object Instance from JSON in .NET?

Since Object Initializers are very similar to JSON, and now there are Anonymous Types in .NET. It would be cool to be able to take a string, such as JSON, and create an Anonymous Object that represents the JSON string.
Use Object Initializers to create an Anonymous Type:
var person = new {
FirstName = "Chris",
LastName = "Johnson"
};
It would be awesome if you could pass in a string representation of the Object Initializer code (preferably something like JSON) to create an instance of an Anonymous Type with that data.
I don't know if it's possible, since C# isn't dynamic, and the compiler actually converts the Object Initializer and Anonymous Type into strongly typed code that can run. This is explained in this article.
Maybe functionality to take JSON and create a key/value Dictionary with it would work best.
I know you can serialize/deserializer an object to JSON in .NET, but what I'm look for is a way to create an object that is essentially loosely typed, similarly to how JavaScript works.
Does anyone know the best solution for doing this in .NET?
UPDATE: Too clarify the context of why I'm asking this... I was thinking of how C# could better support JSON at the language level (possibly) and I was trying to think of ways that it could be done today, for conceptual reasons. So, I thought I'd post it here to start a discussion.
There are languages for .NET that have duck-typing but it's not possible with C# using Dot.Notation since C# requires that all member references are resolved at compile time. If you want to use the Dot.Notation, you still have to define a class somewhere with the required properties, and use whatever method you want to instantiate the class from the JSON data. Pre-defining a class does have benefits like strong typing, IDE support including intellisense, and not worrying about spelling mistakes. You can still use anonymous types:
T deserialize<T>(string jsonStr, T obj) { /* ... */}
var jsonString = "{FirstName='Chris', LastName='Johnson, Other='unused'}";
var person = deserialize(jsonString, new {FirstName="",LastName=""});
var x = person.FirstName; //strongly-typed
You should check out the JSON.net project:
http://james.newtonking.com/pages/json-net.aspx
You are basically talking about the ability to hydrate an object from JSON, which this will do. It won't do the anonymous types, but maybe it will get you close enough.
I wrote a relatively short method that will Parse JSON and return a name/value Dictionary that can be accessed similarly to the actual object in JavaScript.
Here's a sample usage of the below method:
var obj = ParseJsonToDictionary("{FirstName: \"Chris\", \"Address\":{Street:\"My Street\",Number:123}}");
// Access the Address.Number value
object streetNumber = ((Dictionary<string, object>)obj["Address"])["Number"];
And, here's the code for the ParseJsonToDictionary method:
public static Dictionary<string, object> ParseJsonToDictionary(string json)
{
var d = new Dictionary<string, object>();
if (json.StartsWith("{"))
{
json = json.Remove(0, 1);
if (json.EndsWith("}"))
json = json.Substring(0, json.Length - 1);
}
json.Trim();
// Parse out Object Properties from JSON
while (json.Length > 0)
{
var beginProp = json.Substring(0, json.IndexOf(':'));
json = json.Substring(beginProp.Length);
var indexOfComma = json.IndexOf(',');
string endProp;
if (indexOfComma > -1)
{
endProp = json.Substring(0, indexOfComma);
json = json.Substring(endProp.Length);
}
else
{
endProp = json;
json = string.Empty;
}
var curlyIndex = endProp.IndexOf('{');
if (curlyIndex > -1)
{
var curlyCount = 1;
while (endProp.Substring(curlyIndex + 1).IndexOf("{") > -1)
{
curlyCount++;
curlyIndex = endProp.Substring(curlyIndex + 1).IndexOf("{");
}
while (curlyCount > 0)
{
endProp += json.Substring(0, json.IndexOf('}') + 1);
json = json.Remove(0, json.IndexOf('}') + 1);
curlyCount--;
}
}
json = json.Trim();
if (json.StartsWith(","))
json = json.Remove(0, 1);
json.Trim();
// Individual Property (Name/Value Pair) Is Isolated
var s = (beginProp + endProp).Trim();
// Now parse the name/value pair out and put into Dictionary
var name = s.Substring(0, s.IndexOf(":")).Trim();
var value = s.Substring(name.Length + 1).Trim();
if (name.StartsWith("\"") && name.EndsWith("\""))
{
name = name.Substring(1, name.Length - 2);
}
double valueNumberCheck;
if (value.StartsWith("\"") && value.StartsWith("\""))
{
// String Value
d.Add(name, value.Substring(1, value.Length - 2));
}
else if (value.StartsWith("{") && value.EndsWith("}"))
{
// JSON Value
d.Add(name, ParseJsonToDictionary(value));
}
else if (double.TryParse(value, out valueNumberCheck))
{
// Numeric Value
d.Add(name, valueNumberCheck);
}
else
d.Add(name, value);
}
return d;
}
I know this method may be a little rough, and it could probably be optimized quite a bit, but it's the first draft and it just works.
Also, before you complain about it not using regular expressions, keep in mind that not everyone really understands regular expressions, and writing it that way would make in more difficult for others to fix if needed. Also, I currently don't know regular expression too well, and string parsing was just easier.
You can't return an anonymous type from a method**, so a "rehydrated" anonymous type's existence would be limited to the method in which it is rehydrated. Kind of pointless.
** You can return it as an object (which requires reflection to access its properties--yeech) or you can "cast it by example", which is pointless as well, since it takes extra steps and it means you already KNOW what the object's type should look like, so why not just create an object and fill it up in the first place?
What is the application for this?
I would not go down this road for a few reasons.
First; it may require a lot of support code using reflection and such to create the transparent method that you are talking about.
Second, like you said, C# is a strongly typed language and things like these were left out of the language specification for a reason.
Third, the overhead for doing this would not be worth it. Remember that web pages (especially AJAX queries) should be really fast or it defeats the purpose. If you go ahead and spend 50% serializing your objects between C# and Javascript then you have a problem.
My solution would be to create a class that just encapsulates a dictionary and that takes a JSON string as a ctor argument. Then just extend that class for each type of JSON query you want to handle. This will be a strongly typed and faster solution but still maintain extensibility and ease of use. The downside is that there is more code to write per type of JSON request.
:)

Categories