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.
:)
Related
I am trying to understand the DynamicDictionary in NancyFX, it looks pretty cool. Does anyone know of a blog post or similar, that goes through the internals of it?
I need a propertybag to pass around objects, that I don't know the content of because they come from outside my system as JSON. But based on the contents of these objects, such as the presence of certain properties I need to do stuff.
I could just pass around dynamic objects, but that is a bit too vague I think. Don't really like that.
I would need nested dictionaries, to fully represent the object graph.
The dynamic dictionary is just a ExpandoObject with a Dictionary in it. So it can still be accessed like a dictionary.
For example, in MVC you access Form properties like so:
var name = Request["name"];
or
var name = Request.Form["name"];
When a request comes into Nancy you can access it via the dot notation. Or via the class indexer.
var name = parameters.name;
var name = parameters["name"];
This is handy when you're sending query string or form names that have values that cannot be used in dot notation.
var firstName = parameters["first-name"];
The values are also dynamic, so it could be made up of nested objects. This allows you to do stuff like:
var firstName = parameters.contact.firstname;
So if you're passing a JSON payload to the request then you can access the entire structure using dot notation.
However you will probably find most developers using Nancy only ever access Route values or QueryString values using this method.
Get["/products/{id:int}/"] = parameters => {
int id = parameters.id;
};
So back to the original question:
Is there a blog post or any doco: Nope.
Why does it exist: For sugar syntax.
Can I use it for what I want: Yes absolutely!
Can you tell me how to use it: Nope, however it shouldn't be hard. Just look the model binding in Nancy to figure it out. It's not too hard.
Just an edit based on the answer by the OP.
When you access the dot notation, continued dot notation will only work on further dynamic types.
This means using var will cause an exception because of the way var and dynamic are handled by the compiler.
When you do:
var person = parameters.person;
var name = person.name;
parameters is currently dynamic and implements TryGetMember, this internally looks up a dictionary of values and attempts to return the value.
When you define the object as var for the person variable. The compiler assumes that anything after that exists on the object, so it looks for name on the person variable.
Since name does not exist as a member of person it will throw.
To resolve this, the variable must be assigned as dynamic. So the example becomes:
dynamic person = parameters.person;
var name = person.name;
This will work.
So I started working with the DynamicDictionary and it is pretty cool and easy to work with. Only one thing bugs me right now. That is if I nest DynamicDictionaries.
Look at the following example:
private void TestNestedDynamicDictionary()
{
dynamic dictionary = new DynamicDictionary();
dynamic nestedDictionary = new DynamicDictionary();
nestedDictionary.Add("name", "Peter");
dictionary.Add("person", nestedDictionary);
var person = dictionary.person;
var name = person.name;
Console.WriteLine(name);
}
This fails when trying to access person.name with a 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
DynamicDictionaryValue' does not contain a definition for 'name'
If I just do an explicit cast like this it works.
var person = (DynamicDictionary)dictionary.person;
Any input on how I could make it behave as DynamicDictionary right out of the box... apart from checking the DynamicDictionaryValue before it is returned, and do the cast there, which I think is messy.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
object value;
if (!dictionary.TryGetValue(binder.Name, out value))
{
result = new DynamicDictionaryValue(null);
return true;
}
var dictVal = value as DynamicDictionaryValue;
if (null != dictVal && dictVal.Value is DynamicDictionary)
{
result = dictVal.Value;
}
else
{
result = value;
}
return true;
}
I am too lazy to type out all the properties of my object, so instead of this:
myObj.property1 = value1;
myObj.property2 = value2;
myObj.property3 = value3;
myObj.property4 = value4;
myObj.property5 = value5;
...
Is there way to just do this?
Object myObj = new Object();
foreach (string curProperty in myCollection.AllKeys) {
var curValue = collection[curProperty];
myObj[curProperty] = curValue; // ??????????????
}
Yes, you'll need to use System.Reflection to get the job done:
for (int i = 1; i < 6; i++)
{
PropertyInfo prop = myObj.GetType().GetProperty(string.Format("property{0}", i);
if (prop == null) { continue; }
prop.SetValue(myObj, collection[prop.Name], null);
}
In this example I'm assuming that collection has a string indexer on property name (you may need to recover it a different way). I'm also assuming there are only 5 properties (i < 6), you'll need to set that accordingly. But you get the idea.
In the spirit of the comment made by Jim Mischel, serialization is an option as well. I'm not going to work out an example here because I'm not 100% on the code, but consider web services. Web services do all their work with (de)serialization.
So, you could technically deserialize an XML file into an object and you would get all of the benefits of deserialization - and there are quite a few. One that I can think of off the top of my head is that a new instance of the object is not created before setting the values of the properties - how the framework does that I'm not sure - but I know it's done because I chased a bug like that one time!
You can do this with reflection, but keep in mind that this will be quite a bit slower than doing it properly.
It should be something like this:
var prop = typeof(SomeType).GetProperty(propertyName);
prop.SetValue(myObj, newValue, null);
This assumes that the property exists and is accessible.
You can improve the performance of this significantly using expression trees and saving the newly-created lambdas in memory, but that is a bit complex to write.
Overall, I'd say "don't do this" unless you're just using it as an exercise to learn how to use reflection.
Use System.Reflection and the code would look like this:
Object myObj = new Object();
foreach (string curProperty in myCollection.AllKeys) {
var property= typeof(Object).GetProperty(curProperty);
property.SetValue(myObj, curValue, null);
}
I know it is not exactly what you are asking for and reflection solves the specific question you are asking; but the Expando object is great if you are lazy and you already have a key/value collection. This way you don't even need to declare a class at all!!!
ExpandoObject
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.
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.
EDIT AGAIN: the solution was probably different from my original question. Thanks everyone very much your great ideas. I wish I could vote for more than one answer.
EDIT: I am populating a Jquery table plugin from datatables/.net and it requires the data (Json) to be in a certain format like this;
"sEcho": 1,
"iTotalRecords": 57,
"iTotalDisplayRecords": 57,
"aaData": [
[
"Gecko",
"Firefox 1.0",
"Win 98+ / OSX.2+",
"1.7",
"A"
],
[
"Gecko",
"Firefox 1.5",
"Win 98+ / OSX.2+",
"1.8",
"A"
],
...
]
}
I am recieving data from a service that is returning a collection of object. I would like one method which I can pass these collections into and it will return the appropriate string
thanks
END EDIT
I would like to build a method that can receive and object that we build and will return an array List each containing the value of each object passed in. For example;
I have a collection of 'Car' objects
What I would like to do is
public object[] Something<T>(_cars)
{
object[] objArray = new object[_cars.Count];
foreach(Car _car in _cars ){
IList objList = new List<string>;
objList.Add(_car.Color);
objList.Add(_car.EngineSize);
//etc etc
objArray[i] = objList;//i'll have to use a for loop to get the i counter but you get my idea
}
return objArray
}
my problem is how can I access the properties of the object without knowing what type of object it is?
thanks for any help
Update: To answer your revised question - produce a JSON result of a data structure - use the built-in JavaScriptSerializer class:
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = seriaizer.Serialize(myObjectOrArray);
Below is the previous answer.
how can I access the properties of the object without knowing what type of object it is
Using Reflection, and grabbing the properties which are strings. Note this is not necessarily a good idea. The fact that you have to use reflection to get what you want is usually a HUGE WARNING FLAG that your design is wrong.
However, in the hopes of learning something useful, here's how it could be done:
public object[] Something<T>(T[] items)
{
IList objList = new List<object>();
//get the properties on which are strings
PropertyInfo[] properties = typeof(T).GetProperties().Where(p => p.PropertyType == typeof(string));
foreach(T item in items)
{
IList stringList = new List<string>;
foreach(PropertyInfo property in properties)
{
objList.Add(property.GetValue(item, null) as string);
}
objList.Add(stringList);
}
}
return objList.ToArray();
}
A far, far better solution would be to require all the objects coming into this method to conform to some interface that requires them to provide their own string-formatted data. Or maybe take two steps back and ask for help on the underlying problem. This approach is fraught with problems. It's a rabbit hole you don't want to go down.
Use the System.Web.Script.Serialization.JavaScriptSerializer class. It was specifically provided for JSON serialization.
using System.Web.Script.Serialization;
public string ToJson(object o)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(o);
}
EDIT: Oops, I missed that your plugin doesn't want a true JSON representation of the objects; it just wants arrays of values. You could use reflection to iterate over the properties of the objects as others have suggested, but then you have no control over which properties end up in which columns. It is not clear from your question whether that is a problem for you.
If you need a strict mapping between properties and columns, then you will have to define that somehow in C#. To do this you could implement IEnumerable as Ed demonstrates or create a custom interface:
public interface ITableDataSource
{
IList<string> GetTableData();
}
Then implement this on any objects that might need to be data sources for the jQuery table plugin:
public class Car : ITableDataSource
{
//...class implementation details...
public IList<string> GetTableData()
{
return new List<string>()
{
this.Color,
this.EngineSize,
this.NumberOfSeats.ToString()
};
}
}
Finally, in your method that is returning the data to the jQuery plugin, use the interface to construct your response object, then pass it to my ToJson() method to serialize it:
public string DoSomething(IList<ITableDataSource> objects)
{
var result = new
{
sEcho = 1,
iTotalRecords = 1,
iTotalDisplayRecords = 1,
aaData = new List<IList<string>>()
};
foreach (ITableDataSource ds in objects)
result.aaData.Add(ds.GetTableData());
return ToJson(result);
}
While it would be relatively straightforward to use reflection to loop through all of your objects and all the properties on those objects to build that string, it's already been written.
I would highly recommend looking at the Json.NET project found here. Add this DLL to your project and converting a list of objects into a Json formatted string is as easy as:
string json = Newtonsoft.Json.JsonConvert.SerializeObject( listOfCars );
IList objList = new List<string>();
foreach ( PropertyInfo prop in _car.GetType().GetProperties() )
{
var value = prop.GetValue( _car, null );
objList.Add( value != null ? value.ToString() : null );
}
objArray[i] = objList;
The code to get the Property values of an object is
foreach (PropertyInfo info in myObject.GetType().GetProperties())
{
if (info.CanRead)
{
object o = propertyInfo.GetValue(myObject, null);
}
}
my problem is how can I access the properties of the object without knowing what type of object it is?
Well, in the general sense you can't. Generics is all about treating objects generically. However, you can impose type constraints by using a where clause. Based on the foreach loop I would say constrain your types to types that implement IEnumerable, but then you go on to use properties like "Color" and "EngineSize", which are very specific. I don't even know why you would have properties named "Color" and "EngineSize" that are strings, but that is another problem altogether...
It seems like the best approach for you would be to define an interface or an abstract base class that each of these objects inherits from. Then you can use the 'where' clause to constrain to objects of that interface/base class only So...
public object[] Something<T>( T _cars) where T : IEnumerable<MyInterface>
However, if we are going to go down this road I don't see why the method should be generic at all. It could simply take an IEnumerable<T> as an input. When we only want to use one type in a method generics is not needed.