I deserialize a JSon string that holds an object with an array of subobjects.
The current working solution looks like this:
var definition = new { systems = new subclass[0] };
var ret = JsonConvert.DeserializeAnonymousType(source, definition);
public class subclass
{
public long id;
}
Is there a way to replace the subclass with another anonymous one?
I tried using the following, but only get a compiler error:
var definition = new { constellations = new{ id=0L }[0] };
I wonder if you could do:
var definition = new { systems = MakeEmptyArrayFrom(new { id = 0L}) };
...
static T[] MakeEmptyArrayFrom<T>(T value) => new T[0];
note: if that works, it will probably also work even if you use something like:
static T[] MakeNullArrayFrom<T>(T value) => null;
as I imagine the library is more interested in the Type than the value.
Related
I'm getting some JSON as a string and storing it as such:
private static List<object> history = new List<object>();
var data = JsonConvert.DeserializeObject(parsedData);
history.Add(data);
The JSON data looks something like this:
{ id: 12, data: 'my data' }
I'd like to add another method that iterates through the history list, finds an item by its ID and updates it.
What's the best way to access properties on objects like this?
If the incoming JSON string always has the same fields, you can serialize it to a defined class/type.
public class JsonHistory
{
public int id { get; set; }
public string data { get; set; }
}
List<JsonHistory> history = new List<JsonHistory>();
var histData= JsonConvert.DeserializeObject<JsonHistory>(parsedData);
history.Add(histData);
You can also then use linq to find any matches you are looking for:
var matches = history.Where(x => x.id == 10).Select(x => x.data);
You can use dynamic instead of object, because it is easier to use properties rather than object
List<dynamic> history = new List<dynamic>();
string parsedData = "{ id: 12, data: 'my data' }";
var data = JsonConvert.DeserializeObject<dynamic>(parsedData);
history.Add(data);
history.Add(data);
foreach (var o in history)
{
o.id = 13;
}
Also, I strongly suggest you to create a class and use it as known type. That will give you intellisense and definitely you will need that further.
The JSON.NET documentation has the following approach, that I would also suggest using:
First - deserialise to a sensible type (anonymous is fine)
var json = "{id: 12, data: 'my data'}";
var definition = new { Id = 0, Data = "" }
var deserialised = JsonConvert.DeserializeAnonymousType(json, definition);
Second - you've got your first item, so you can "trick" the compiler into letting you use the anonymous type in a list:
var history = (new[] { deserialised }).ToList();
You can then shove any other deserialised instances into that list.
Now you can do your filtering:
var itemImLookingFor = history.SingleOrDefault(x => x.Id == 10);
Once you've then got the item, you can just update it:
itemImLookingFor.Data = itemImLookingFor.Data.ToUpperCase()
I'd recommend reading this as it explains some of the shortcomings inherent in using the dynamic keyword; it's not a bad thing to do, it just has its place.
For this scenario, JSON.NET gives you all the tools you need to either deserialise to a type of your own defining (e.g. write a class that mirrors the JSON, or to an anonymous type like I've done here).
The usual approach is to either deserialize to a custom class or to deserialize to JObject which would allow you to iterate over its properties like using reflection. Both require a lot of typing.
But you can use a clever little trick and get all the benefits of a strong type without having to write the class.
Use an anonymous duck type
Add this method to your library somewhere:
static public T JsonDeserialize<T>(string input, T template)
{
return JsonConvert.DeserializeObject<T>(input);
}
Once you have this in place, you can use it to duck-type the JSON (i.e. get the compiler to infer an anonymous type) by supplying an example instance. This allows you to use anonymous types instead of typing up a custom class.
So for example, to get the row with ID 12, you do something like this:
using System;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
static public T JsonDeserialize<T>(string input, T example)
{
return JsonConvert.DeserializeObject<T>(input);
}
public static void Main()
{
//Sample data with two records
const string input = #"[ { 'id' : 12, 'data' : 'MyData' }, { 'id' : 13, 'data' : 'Another record' } ]";
//Create an example instance so the compiler can use its anonymous type
var example = new []
{
new { id = default(int), data = default(string) }
};
//Pass the example as argument 2 so that the compiler can infer T. The argument itself isn't used for anything.
var list = JsonDeserialize(input, example);
//Now we have a strongly-typed list, without having to write a class
//We can use LINQ or anything else that needs a strong type
foreach ( var o in list.Where( a => a.id == 12) )
{
Console.WriteLine(o.id);
Console.WriteLine(o.data); //Intellisense works here
}
}
}
Output:
12
MyData
Working example on DotNetFiddle.
During the development of one of my projects, I encountered an issue regarding generic types.
The project requires me to write a class that would act as a source of list objects. Suppose I had the following class:
public class TablesProvider
{
private readonly List[] _tables;
public TablesProvider()
{
// initialize the tables var here....
}
public List<TItem> GetTable<TItem>()
{
return (List<TItem>)_tables.Single(x => x is List<TItem>);
}
}
This class obviously doesn't work, because the List type is a generic type and therefore the generic arguments should be specified.
So I made an abstract type called MyList, that would be derived by a more specific type MyList<TItem> in order to escape this requirement, and edited the TablesProvider a little.
public class TablesProvider
{
private readonly MyList[] _tables;
public TablesProvider()
{
// initialize the tables var here....
}
public MyList<TItem> GetTable<TItem>()
{
return (MyList<TItem>)_tables.Single(x => x is MyList<TItem>);
}
}
public abstract class MyList
{
// ...
}
public class MyList<TItem> : MyList, IList<TItem>
{
private readonly List<TItem> _elements = new List<TItem>();
public TItem this[int index]
{
get { return _elements[index]; }
set { _elements[index] = value; }
}
// ...
}
This works quite well. There is only one problem left. Suppose I had 45 different collections, each defined with a different generic argument. What would be the best way of initializing all of those collections? I cannot use a for loop here, since generic parameters are specified at compile-time and not at runtime, and therefore a construction like this wouldn't be possible:
for (int i = 0; i < 45; i++)
_tables[i] = new MyList<GenericParameters[i]>();
My ultimate goal is to have the luxury to just do something like this...
var table = _tablesProvider.GetTable<SomeClass>();
var element = table[3];
var propertyValue = element.SomeProperty;
... without the need to cast the variable element in order to access its type-specific members.
It is probably worth mentioning that the amount of different list objects is fixed to 45. This will not change. In theory, I could initialize the array line by line, or have 45 properties or variables instead. Both of these options, however, sound as a rather cheap solution to me, but I will accept one of them if there is no other way.
Any of you got some ideas? Am I doing this completely wrong? Should I consider an other structure?
Thanks in advance.
Yes, it is possible to do what you are describing if you use reflection.
Supposing that your hypothetical GenericParameters array is an array of Types (since you can't have an array of type identifiers), you can define this helper function:
private MyList MakeList(Type t)
{
return (MyList)Activator.CreateInstance(typeof(MyList<>).MakeGenericType(t));
}
And that will allow you to do this:
public TablesProvider()
{
var GenericParameters = new[] { typeof(string), typeof(int), typeof(DateTime) };
_tables = new MyList[GenericParameters.Length];
for (int i = 0; i < GenericParameters.Length; i++)
{
_tables[i] = MakeList(GenericParameters[i]);
}
}
You can even use LINQ if you want:
public TablesProvider()
{
var GenericParameters = new[] { typeof(string), typeof(int), typeof(DateTime) };
_tables = GenericParameters.Select(MakeList).ToArray();
}
Previous answer:
Well, the reality is that you're going to have a list of 45 different types somewhere, which pretty much means you're going to have 45 different lines of similar code. So one could say the goal is to make those lines as concise as possible.
One way to do so would be to add a helper function:
private void AddTable<T>()
{
_tables.Add(new MyTable<T>());
}
(this assumes changing _tables to a List<MyTable>)
Then you could just do:
AddTable<Type1>();
AddTable<Type2>();
AddTable<Type3>();
AddTable<Type4>();
this implementation works
public class TablesProvider
{
private readonly List<object> _tables;
public TablesProvider()
{
_tables = new List<object>();
}
public IList<TItem> GetTable<TItem>()
{
var lst = (List<TItem>)_tables.SingleOrDefault(x => x is List<TItem>);
if (lst == null)
{
lst = new List<TItem>();
_tables.Add(lst);
}
return lst;
}
}
it creates List of TItem when necessary; next time it returns the same list for TItem. it is lazy initialization
so you can do invoke
var table = _tablesProvider.GetTable<SomeClass>();
without any code like this:
for (int i = 0; i < 45; i++)
_tables[i] = new MyList<GenericParameters[i]>();
it is not ThreadSafe
var _Contact = new ContactLstModel {
ContactName="xxxxxx",
EmailAddr="yyyyyy",
ContactNo="ddddddd",
SelectedContactType="dddd"
};
var _ContactOption= new ContactLstModel{
ContactType= new List<SelectListItem>(){
new SelectListItem{
Text="sss",Value="ddd"
}
}
};
as you can see both are of the same model ContactLstModel. Now how do I combine both into one?
Like in jQuery, we have $.extend(dest,source);
Is there an equivalent in C#?
There is not a built-in equivalent of $.extend in C# and .NET 4.5.
However you can find many examples of people trying to achieve that kind of behavior using reflection in .NET. There are others who use serialization (JSON.NET etc.) to achieve similar behaviors . Another approach would be to use IOC containers like Automapper.
Here is an example how to merge your first object into the second object using Automapper IOC:
var expr = Mapper.CreateMap<ContactLstModel, ContactLstModel>().ForMember("ContactType", (conf) => { conf.Ignore(); });
var merged = Mapper.Map<ContactLstModel, ContactLstModel>(_Contact, _ContactOption);
With Automapper you can control how to map each single property from source to destination.
If you don't want external library dependencies, and want full control you can use a pure Reflection approach.
For example you could use something similar as the CopyValues method from this link and merge the second object properties with the first one using reflection.
CopyValues<ContactLstModel>(_Contact, _ContactOption);
So this line of code will copy the ContactType property values from the second object into the first one.
CopyValues uses reflection to loop through the properties of the objects:
public static void CopyValues<T>(T target, T source)
{
Type t = typeof(T);
var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(source, null);
if (value != null)
prop.SetValue(target, value, null);
}
}
Of course this does not support everything jquery extend does (merging, shallow and deep cloning into a new object etc.), but it can satisfy your current needs. You can extend on these principles and build a more comprehensive solution.
However have in mind that C# is not a language like Javascript, and the cost of doing reflection is much higher in C#, while in Javascript the properties of a prototype can be listed with a cheap for-in iteration, or with a call to Object.keys().
You could do it with an extension method:
public static class ContactModelExtensions {
public static ContactModel Extend(this ContactModel first, ContactModel replacement) {
if (!replacement.ContactsName.IsNullOrEmpty()) // or whatever criteria you want
{
first.ContactsName = replacement.ContactsName;
}
// similar assignment for all other properties
return first; // since we return the first one, properties not set in override
// will be untouched
}
}
Now, you can just
var extendedContact = _Contact.Extend(_ContactOptions);
to get it done.
You can use some frameworks for do it. For example with ValueInjecter:
public class NoNullsInjection : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name == c.TargetProp.Name
&& c.SourceProp.Value != null;
}
}
class A
{
public string a { get; set; }
public string b { get; set; }
}
static void Main(string[] args)
{
A a1 = new A() { a = "123" };
A a2 = new A() { b = "456" };
A c = new A();
c.InjectFrom(new NoNullsInjection(),a1,a2);
// "c" now have a="123", b="456"
}
Goal: call a method that returns an Expression I can use to chain methods on an anonymous IQueryable.
Example:
var allProducts = from p in ctx.Products;
var customWhere = Product.GiveMeYourQuery();
var productsIWant = allProducts.Where(customWhere);
Console.Writeline("yeaaaaah!");
This is what I've come up with as to now, which, of course, doesn't work:
class MainClass
{
public static void Main(string[] args)
{
var list = new [] {
new { Name = "ciao", Age = 18 },
new { Name = "prova", Age = 28 },
new { Name = "mah", Age = 38 },
new { Name = "boh", Age = 48 }
};
var myAnon = list.Where(x => x.Name.Length > 2).AsQueryable();
var thisthat = new MainClass();
var subset = myAnon.Where(thisthat.Where);
}
public Expression<Func<T, bool>> Where<T>(T anon){
var expr = Expression.Lambda(Expression.Equal(Expression.Constant(anon), Expression.Constant(anon)));
return (Expression<Func<T, bool>>) expr;
}
}
Compiler wisdom:
../Program.cs(24,24): Error CS0407: A method or delegate 'System.Linq.Expressions.Expression LINQInjector.MainClass.Where(anonymous type)' return type does not match delegate `bool System.Func(anonymous type)' return type (CS0407) (LINQInjector)
I feel I'm pretty close, but I cannot really see the path.
Unfortunately I cannot just cast the a' object to a type I create because what the program should output is the SQL (yes, I'm basically building a querybuilder that feeds another tier the queries to execute) and because I'd have to create too many types anyway (each type for each possible chain of joins between tens of tables).
EDIT:
While I appreciate you trying to show me alternatives and workarounds, at this point I think there's none. This is my question: how to inject Expressions into an anonymous type. If this cannot be done just say so.
Since you want to access a property known at compile time of an object outside of the scope in which it's created, you don't want to use an anonymous object. An anonymous object would be appropriate if you're accessing it using lambdas created in the same scope in which the anon object is created, but you don't want to do that. You want to have another method statically access a property of that object. Just give it a name, it'll make everything super easy:
public class Foo
{
public string Name{get;set;}
//...
}
public static Expression<Func<Foo, bool>> NameEquals(string name)
{
return foo => foo.Name == name;
}
Can I cast ExpandoObject to anonymous type ?
var anoObj = new { name = "testName", email = "testEmail" };
dynamic expandoObj = new System.Dynamic.ExpandoObject();
// Here I'm populating the expandoObj with same property names/types in anonymoustype(anoObj)
// Now, how to convert this ExpandoObject to anonymoustype ?
var newObj = (typeof(anoObj)expandoObj); // This doesn't work
Added Later
// This is my entity
public class Customer
{
#region Public Properties
[ColumnAttribute(Name = "IdColumn")]
public string Id { get; set; }
[ColumnAttribute(Name = "NameColumn")]
public string Name { get; set; }
[ColumnAttribute(Name = "AddressColumn")]
public string Address { get; set; }
[ColumnAttribute(Name = "EmailColumn")]
public string Email { get; set; }
[ColumnAttribute(Name = "MobileColumn")]
public string Mobile { get; set; }
#endregion
}
// -------------------------------------------------------------------------------------
public class LookupService<TEntitySource>
{
public LookupService ()
{
}
public LookupShowable<TEntitySource, TSelection> Select<TSelection>(Expression<Func<TEntitySource, TSelection>> expression)
{
var lookupShowable = new LookupShowable<TEntitySource, TSelection>();
return lookupShowable;
}
}
public class LookupShowable<TEntitySource,TSelection>
{
public LookupShowable()
{
}
public LookupExecutable<TEntitySource, TSelection, TShow> Show<TShow>(Expression<Func<TEntitySource, TShow>> expression)
{
var lookupExecutable = new LookupExecutable<TEntitySource,TSelection,TShow>();
return lookupExecutable;
}
}
public class LookupExecutable<TEntitySource, TSelection, TShow>
{
public TSelection Execute()
{
// Here I want to create a new instance of TSelection and populate values from database and return it.
}
}
//--------------------------------------------------------------------------------------
// This is How I want to call this from front end...
var lookupService = new LookupService<Customer>();
var lookupSelection = lookupService.Select(C => new { C.Id, C.Name, C.Mobile }).Show(C => new { C.Id, C.Name}).Execute();
string sID = lookupSelection.Id;
string sName = lookupSelection.Name;
string sMobile = lookupSelection.Mobile;
Dont think about this middle part.. Purpose of it is another one...
My problem is in Execute() method in LookupExecutable class. I dont know how to create a new instance of TSelection type and assign values to it. This TSelection type is always an anonymous type..
EDIT: I think this question is a prime example of the XY problem. The correct solution doesn't need to concern itself with ExpandoObject or anonymous types, and it would be most likely wrong if it did.
You're looking at it the wrong way. You don't need to create an instance of an anonymous object, you need to invoke the code that is passed to you in an expression (which may or may not be creating an anonymous object).
If you can create an instance of TEntitySource, then that's simple: Compile() the Expression that you got in Select() and then invoke it for each instance of TEntitySource.
If you can't create TEntitySource, you could still do it by rewriting the Expression (using ExpressionVisitor), so that its input is not TEntitySource, but some type you have. But that would require some work from you.
Original answer:
No, that won't work. That's simply not how casting or anonymous types work in C#.
You can't cast between any two types and expect it to work. Either the object you're casting needs to be the type you're casting to, or one of the two types needs to specify a matching cast operator.
The fact that the target type is an anonymous type doesn't change anything (except that you can't even try to cast to an anonymous type directly, because you can't name it; the way you're using typeof() is wrong).
The fact that the source type is dynamic changes things a bit. But only in that the search for the cast operator is done at runtime, not at compile time, and you can even create the cast operator at runtime (see DynamicObject.TryCast()). But that's it, it doesn't add any “magical” cast operators.
The only way I can imagine something like this working would be if you used a variant of “cast by example” and reflection:
public T Convert<T>(ExpandoObject source, T example)
where T : class
{
IDictionary<string, object> dict = source;
var ctor = example.GetType().GetConstructors().Single();
var parameters = ctor.GetParameters();
var parameterValues = parameters.Select(p => dict[p.Name]).ToArray();
return (T)ctor.Invoke(parameterValues);
}
You could then use it something like this:
var expando = new ExpandoObject();
dynamic dynamicExpando = expando;
dynamicExpando.Foo = "SomeString";
dynamicExpando.Bar = 156;
var result = Convert(expando, new { Foo = "", Bar = 1 });
Note that you can't actually invoke Convert() dynamically (by passing it dynamicExpando), because that would mean it would return dynamic too.
Use JavaScriptSerializer to convert the ExpandoObject to any Type as follows:
.....
dynamic myExpandoObject = new ExpandoObject();
var result = ConvertDynamic<myType>(myExpandoObject);
.....
public T ConvertDynamic<T>(IDictionary<string, object> dictionary)
{
var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var obj = jsSerializer.ConvertToType<T>(dictionary);
return obj;
}
This should do the job.
here you have an object made from an ExpandoObject
var anoObj = new { name = "testName", email = "testEmail" };
dynamic expandoObj = new System.Dynamic.ExpandoObject();
object newObj = expandoObj;
But beware, dynamic objects are very very expensive in resource matters, and what you are asking for does not seem to have any sense. A good aproach for what you are asking in the comments supposing you have to deal with dynamic objects and you want to do something with them:
dynamic expando = new System.Dynamic.ExpandoObject();
var myObj = new Dictionary<string, object>();
myObj["myProperty"] = expando.myProperty;
Any dynamyc object is easily casted to a <string, object> typed Dicionary.
Hope that helps!