How to use JsonSerializer.Deserialize with SerializationContext and generics - c#

I m using the following overload that works:
(T)JsonSerializer.Deserialize(contentStream, typeof(T), _serializationContext)!;
But I m wondering if their is a better overload that would return directly the generic type instead of object

Related

C# How to cast from Type without IConvertible using reflection

My returning value of the method CastTo is from the wrong type.
The method CastTo has a returning parameter < T >.
The commented line is what it does without using reflection
//FieldChoice ChoiceProduct = clientContext_temp.CastTo<FieldChoice>(field);
Type FieldChoiceType = sharepointClient.GetType("Microsoft.SharePoint.Client.FieldChoice");
object FieldChoice = Activator.CreateInstance(FieldChoiceType, sharepointClient, web.);
MethodInfo castToMethodInfo = typeclientContext.GetMethod("CastTo");
MethodInfo genericCastTo = castToMethodInfo.MakeGenericMethod(field.GetType());
var ChoiceProduct = genericCastTo.Invoke(clientContext, new object[] { field });
ChoiceProduct = Convert.ChangeType(ChoiceProduct, FieldChoiceType);
Choiceproduct is from the type Field but should be from the type FieldChoice.
The problem is, i can't create an instance of Fieldchoice before the method cause sharepoint just doesn't have a fittable constructor to allow creating it and i can't cast it to the Type with using Convert.changeType cause it doen't have a IConvertible implementation.
Is there any other way i can cast my variable or change the return type of the method?
I think that your problem is that you're passing field object to genericCastTo instead of FieldChoice.

The type arguments for method … cannot be inferred from the usage. Try specifying the type arguments explicitly

I'm not sure, why calling Map2 gives me
The type arguments for method 'Program.Map2(object,
Func)' cannot be inferred from the usage. Try specifying the
type arguments explicitly.
Here is the code...
void Test()
{
var test1 = Map1(1, MapIntToString);
var test2 = Map2(1, MapIntToString);
}
To Map1<From, To>(From value, Func<From, To> mapFunc) => mapFunc(value);
To Map2<From, To>(object value, Func<From, To> mapFunc) => mapFunc((From)value);
string MapIntToString(int value) => Convert.ToString(value);
This is very simplified example. I need to convert some lists of DTOs to Models (and back), but it should be same case...
Because you have defined the parameter of type object while the method MapIntToString has first parameter of type int. So the compiler is not able to figure out that the parameter passed to mapFunc for Map2 i.e object value is currently holding value of type int. Your code will be translated to something like below if we visualize it when will be resolved at run-time but at first place it is not compiling as it's not able to resolve the generic type From:
Map2<Object, String>(object value, Func<object, String> mapFunc) => mapFunc((object)value);
So, obviously this wouldn't work as your method expects parameter of type int not object.
You need to be explicit about the type parameters in this case as Compiler is not smart enough to know that the object value is currently holding value of type int in it.
Being explicit works:
var test2 = Map2<int, string>(1, MapIntToString);
or
var test2 = Map2(1, (Func<int, string>)MapIntToString);
I'm afraid I cannot point to the reason why it does not work implicitly. My personal guess would be that MapIntToString is not a single method, but a Method Group (with one member) that can be converted to a Func<int, string> without problems, but that conversion is not used in resolving generics.

Converting value type array to reference type array

I need to write an exception class that takes a message and an info object of any type (usually anonymous object).
I have the following code:
public SpecialException(string message, object info) : this(message)
{
StringBuilder sb = new StringBuilder();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(info.GetType()))
{
object value = property.GetValue(info);
string valueStr = value.GetType().IsArray ? (value as IEnumerable<object>).Select(x => x.ToString()).Aggregate((x, y) => $"{x}, {y}") : value.ToString();
sb.AppendLine($"{property.Name} = {valueStr}");
}
Info = sb.ToString();
}
The problem is, this code does not work when one of the anonymous object's properties is an array of value-typed items since they do not inherit object and this type of covariance cannot work with them.
What I tried, but found either not to work or inelegant:
Using a Dictionary<string, object> - Cannot override the Add method
Using the IDictionary<string, object> interface - Do not want to implement all of the interface's methods for a simple exception
Using an ExpandoObject and dynamic keyword - Will run into the same problems as the code above
Serializing to JSON using dynamic and Newtonsoft JSON - Do not want a dependancy on a third-party library (or the Web DLL)
I assume there is an elegant way (probably using reflection) to achieve this, perhaps by somehow iterating through the array. Can anyone suggest a solution?
Variance does not work for value types. So that, value type array can not be casted to IEnumerable<object>, but it still can be casted to non-generic IEnumerable interface. After that you can call Cast<object>() extension method to get IEnumerable<object> instance.
((IEnumerable)value).Cast<object>()

How do I get the return type of a delegate type through reflection?

I'm doing reflection-heavy work for a personal project, and I'd need to access the return type of a delegate through its Type object. This is a little meta, so here's an example.
Type type = typeof(Func<Foo, Bar, Baz>);
// ????
// Use reflection to come to the following expected result
Type result = typeof(Baz);
How can I do that?
I won't have any instance of that type to cast into Delegate.
One way would be to get a MethodInfo representing the delegate-type's Invoke method, and then retrieve the method's return type.
var result = type.GetMethod("Invoke").ReturnType;

Define an anonymous structure as a parameter in a method

Can I define an object-structure as a parameter to a method in the parameter declaration without having to create a type?
I am inspired by LINQ to SQL queries, where you are able to return a subset of your query-results in the form of a new object:
var query = from t in dc.Table select new { Foo = t.column };
What you're describing isn't possible. In the case of your Linq to Sql query, the C# compiler creates an anonymous type with a single property named Foo with the same type as t.column. Type inferencing is then used and the variable "query" is actually strongly typed to this anonymous type (which is what gives you intellisense goodness on this variable).
Using "var" as a parameter type isn't possible because the type of the parameter can't be inferred, it requires the calling expression to decide on the actual type of the parameter.
The best that you could do would be to use generics and iterate through properties:
public static void Print<T>(T obj)
{
Type type = typeof(T);
PropertyInfo[] properties = type.GetProperties();
foreach(PropertyInfo pi in properties)
{
Console.WriteLine(pi.Name + ": " + pi.GetValue(obj, null));
}
}
which gives you a "rudimentary" ability to use anonymous types (or any type for that matter) as a parameter.
Nope, you cannot declare an anonymous type as an input parameter, and you cannot return it, unless you return it as an object. See this blog post for a hacky workaround, if you want, but that's really still just boxing and unboxing the type back and forth, so it's not actually better than just treating it as an object.
How useful is a parameter to a function that you can't use directly? Function parameters should help document the function.

Categories

Resources