Cast generic parameter - c#

I get an object back from a method. The object is of type object and I can't change this because of backwards compatibility. If it is of a certain type (Response<T> bellow) then I need to access the property Payload which is of type T so that I can serialize it as part of a another object and send it off. The problem is that since I don't know the type of T I can't cast the object to Response<T> to access Payload even though I don't care about its type.
Here is my object with the generic type:
public class Response
{
public int Status { get; set; }
public string Message { get; set; }
}
public class Response<T> : Response
{
public T Payload { get; set; }
}
Here is what I would like to do:
// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
var payload = ((Response<object>)data).Payload; // Unable to cast object of type...
}
But the only way I could find to do this is by using dynamics.
// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
var payload = ((dynamice)data).Payload;
}
Don't ask why things are the way they are (I'm wondering that myself). I have to do code gymnastics to keep backwards compatibility in this system. I just want compile time checking on the name of the property.
Here is a fiddle: https://dotnetfiddle.net/dXxHbD
UPDATE:
I need to be able to serialize and deserialize this object. Originally Response had a property Payload of type object. This caused serialization issues when Response<T> was deserialized because the Payload property was of type Newtonsoft.Json.Linq.JObject which could not be cast to T. Here is an example: https://dotnetfiddle.net/uc15HD
The problem was that I was going the wrong direction and the deserialization works if I cast T to object rather than try to cast object to T. When I store the value as its specific type T then the serializer knows what to deserialize the string to.
Here is an example using Jon's answer below: https://dotnetfiddle.net/KwudAx
Here is a similar example using Matias' solution of using covariance: https://dotnetfiddle.net/kCjZr4

To get compile-time checking of the name of the property, you can keep the dynamic typing, but get the runtime "mini-compiler" to do the hard work:
object data = LegacyCode();
object payload = GetPayload(data);
// Use payload
...
private static object GetPayload<T>(Response<T> response)
{
return response.Payload;
}
public static object GetPayload(object data)
{
// Fallback method. You could return null here and use
// that to indicate in the calling code that it wasn't a
// Response<T>...
}
A much better solution would be to add an non-generic interface or an extra base class though. For example:
public class Response
{
public int Status { get; set; }
public string Message { get; set; }
}
public interface IPayloadHolder
{
public object Payload { get; }
}
public class Response<T> : Response, IPayloadHolder
{
public T Payload { get; set; }
// By using explicit interface implementation, this
// doesn't get in the way for normal usage.
IPayloadHolder.Payload { get { return Payload; } }
}
Then you can use:
var payloadHolder = data as IPayloadHolder;
if (payloadHolder != null)
{
var payload = payloadHolder.Payload;
}

I believe that you need to use covariance.
Design an interface IResponse<out T>:
public interface IResponse<out T>
{
public T Payload { get; }
}
And implement it on Response<T>. Now you can cast it to IResponse<object>:
Response<string> x = new Response<string>();
IResponse<object> y = x; // implicit cast

Related

C# How to cast from object to a type whose name is available as string

I get an object from a message broker (RabbitMQ) which has a signature similar to the following:
public class ErrorMessage
{
public string MessageId { get; set; }
public string Publisher { get; set; }
public string Error { get; set; }
public string OriginalMessageType { get; set; }
public object OriginalMessage { get; set; }
}
Background information
I do have a C# DLL containing all message type definitions. The messages are not designed for C# specifically, since consumers are written in several programming languages. So the message objects do not contain Generics and other C# goodies. With C# I use the EasyNetQ library to serialize/deserialize messages and as wrapper around the RabbitMQ client driver.
Question / Problem
Is there any way in C# to cast / convert the OriginalMessage property from object to an instance of its original type? The type information is provided as string in the OriginalMessageType property.
I tried something like this (which of course doesn't work...) in my message handler method
public static Task ProcessErrorMessage(IMessage<ErrorMsg> message, MessageReceivedInfo info)
{
var t = Type.GetType(message.Body.OriginalMessageType);
var origMsg = (t)message.Body.OriginalMessageType; //get the original message which caused the error
var someProperty = origMsg.SomeProperty;
// etc.
// process the message using properties of origMsg
// ...
return Task.CompletedTask;
}
If I understood it correctly, you can split your task into 2 steps:
Create a type of the string using OriginalMessageType
Convert an object OriginalMessage to desired type
I guess you can just have a switch statement and cast an object to a specific type, but your task could be different, so
Step #1
To create a type from the string:
Type type = Type.GetType("YourNamespace.YourClass, YourAssembly");
You can use just the name of the type if the type is in mscorlib or the calling assembly:
Type myType1 = Type.GetType("System.Int32");
Please see Type.GetType for more information.
Step #2
To convert an object I would suggest to use Convert.ChangeType which is
Returns an object of the specified type whose value is equivalent to
the specified object.
So it can look like this
dynamic origMsg = (dynamic) Convert.ChangeType(OriginalMessage, YourType);
Small example
using System;
namespace ConsoleApp12
{
class A
{
public int P1 { get; set; }
}
class Program
{
static void Main(string[] args)
{
A myvariable = new A
{
P1 = 1,
};
object obj = myvariable;
string typename = "ConsoleApp12.A";
Type type = Type.GetType(typename);
dynamic origMsg = (dynamic)Convert.ChangeType(obj, type);
Console.WriteLine(origMsg.P1);
Console.ReadKey();
}
}
}
I hope it helps 😊

RedisSessionStateProvider with ProtoBuf serialization causing errors

I am trying to get protobuf serialization working with the RedisSessionStateProvider. I have specified the redisSerializerType as a custom class which implements Microsoft.Web.Redis.ISerializer - here is the deserialization code:
public object Deserialize(byte[] data)
{
return DeserializeDirect(data);
}
private object DeserializeDirect(byte[] data)
{
using (var memoryStream = new MemoryStream(data))
{
return Serializer.Deserialize<object>(memoryStream);
}
return null;
}
As I need to implement Microsoft.Web.Redis.ISerializer the signature for deserialize uses a return type of object and there is no way to pass in the actual type being returned. So when DeserializeDirect tries to use the Protobuf.Serializer to deserialize it (as expected) says "Type is not expected, and no contract can be inferred: System.Object". I am using a web app with .NET framework 4.6.1 and I was hoping somebody could point out what I am doing wrong.
Thanks!
Normally, protobuf-net really wants to know the exact type. You can, however, cheat using DynamicType. This tells protobuf-net to include additional type metadata - something it doesn't usually include.
Note that this can make you code brittle - it may fail if the type changes in you code!
I will be implementing Any soon (as part of 2.3.0), which is another option here.
public static void Main()
{
// the actual object we care about
object obj = new Foo { X = 1 };
// serialize and deserialize via stub
var stub = new Stub { Data = obj };
var clone = Serializer.DeepClone(stub);
// prove it worked
Console.WriteLine(clone.Data);
// prove it is a different instance
Console.WriteLine(ReferenceEquals(obj, clone.Data));
}
[ProtoContract]
public class Foo
{
[ProtoMember(1)]
public int X { get; set; }
public override string ToString() => $"X={X}";
}
[ProtoContract]
public sealed class Stub
{
[ProtoMember(1, DynamicType = true)]
public object Data { get; set; }
}

How to serialize/deserialize a DateTime stored inside an object field using DataContractJsonSerializer?

I use the following class to exchange JSON data over two ASP.NET services :
[DataContract]
public class Filter
{
[DataMember]
public string Name {get; set;}
[DataMember]
public FilterOperator Operator {get; set;}
[DataMember]
public object Value {get; set;}
}
Here is the problem : if I set a DateTime inside Value, it will be deserialized as string :
Value = "/Date(1476174483233+0200)/"
This is probably because deserializer has no clue to know what was the type of the value when serialized initially :
JSON = {"Value":"\/Date(1476174483233+0200)\/"}
As explained here, DataContractJsonSerializer supports polymorphism, with the help of the __type property.
I have tried to add [KnownType(typeof(DateTime))] attribute on the top of the class but it does not help.
However if I set a Tuple<DateTime> inside Value property (and the appropriate KnownType attribute on the class), it works (the value it deserialized properly) :
Value = {(10/11/2016 10:49:30 AM)}
Inside JSON, __type is emited
JSON = {
"Value": {
"__type" : "TupleOfdateTime:#System",
"m_Item1" : "\/Date(1476175770028+0200)\/"
}
}
Is there a way to force DataContractJsonSerializer to emit proper information to serialize/deserialize DateTime properly (which mean I got a DateTime after serialization instead of a string) ?
I have try to set EmitTypeInformation = EmitTypeInformation.Always in DataContractJsonSerializerSettings but it does not help.
The problem is that DataContractJsonSerializer only inserts a polymorphic type hint property "__type" for types that correspond to a JSON object - an unordered set of name/value pairs surrounded by { and }. If the type maps to anything else (i.e. a JSON array or primitive) then there is no place for a type hint to be inserted. This restriction is documented in Stand-Alone JSON Serialization:
Type Hints Apply Only to Complex Types
There is no way to emit a type hint for non-complex types. For example, if an operation has an Object return type but returns a Circle, the JSON representation can be as shown earlier and the type information is preserved. However, if Uri is returned, the JSON representation is a string and the fact that the string used to represent a Uri is lost. This applies not only to primitive types but also to collections and arrays.
Thus what you will need to do is to modify your Filter class to serialized and deserialized a generic surrogate object for its value that encapsulates the value's type information, along the lines the one in this question for Json.Net:
[DataContract]
public class Filter
{
[DataMember]
public string Name { get; set; }
[DataMember]
public FilterOperator Operator { get; set; }
[IgnoreDataMember]
public object Value { get; set; }
[DataMember]
TypedSurrogate TypedValue
{
get
{
return TypedSurrogate.CreateSurrogate(Value);
}
set
{
if (value is TypedSurrogate)
Value = ((TypedSurrogate)value).ObjectValue;
else
Value = value;
}
}
}
[DataContract]
// Include some well-known primitive types. Other types can be included at higher levels
[KnownType(typeof(TypedSurrogate<string>))]
[KnownType(typeof(TypedSurrogate<bool>))]
[KnownType(typeof(TypedSurrogate<byte>))]
[KnownType(typeof(TypedSurrogate<sbyte>))]
[KnownType(typeof(TypedSurrogate<char>))]
[KnownType(typeof(TypedSurrogate<short>))]
[KnownType(typeof(TypedSurrogate<ushort>))]
[KnownType(typeof(TypedSurrogate<int>))]
[KnownType(typeof(TypedSurrogate<long>))]
[KnownType(typeof(TypedSurrogate<uint>))]
[KnownType(typeof(TypedSurrogate<ulong>))]
[KnownType(typeof(TypedSurrogate<float>))]
[KnownType(typeof(TypedSurrogate<double>))]
[KnownType(typeof(TypedSurrogate<decimal>))]
[KnownType(typeof(TypedSurrogate<DateTime>))]
[KnownType(typeof(TypedSurrogate<Uri>))]
[KnownType(typeof(TypedSurrogate<Guid>))]
[KnownType(typeof(TypedSurrogate<string[]>))]
public abstract class TypedSurrogate
{
protected TypedSurrogate() { }
[IgnoreDataMember]
public abstract object ObjectValue { get; }
public static TypedSurrogate CreateSurrogate<T>(T value)
{
if (value == null)
return null;
var type = value.GetType();
if (type == typeof(T))
return new TypedSurrogate<T>(value);
// Return actual type of subclass
return (TypedSurrogate)Activator.CreateInstance(typeof(TypedSurrogate<>).MakeGenericType(type), value);
}
}
[DataContract]
public class TypedSurrogate<T> : TypedSurrogate
{
public TypedSurrogate() : base() { }
public TypedSurrogate(T value)
: base()
{
this.Value = value;
}
public override object ObjectValue { get { return Value; } }
[DataMember]
public T Value { get; set; }
}
Now your JSON will look something like:
{
"TypedValue": {
"__type": "TypedSurrogateOfdateTime:#Question39973917",
"Value": "/Date(1476244800000)/"
}
}

Passing a Variable as a Type WITHOUT using Reflection: 'myvar' is a variable but is used like a type

I've got a simple method that deserializes an xml string to a type that is specified.
public static class TextUtility
{
public static T Deserialize<T>(string xml)
{
...
}
}
That's all good. Where I'm having trouble is in calling this method. The process looks like this:
public interface IMessageReceived
{
string MessageBodyAsXML { get; set; }
string MessageType { get; set; }
}
public class MessageReceived : IMessageReceived
{...}
List<MessageReceived> messageList = new List<MessageReceived>();
Then, in the worker class that is processing the messages, we loop over all the messages received. Inside that loop, we loop over a list of potential message types.
foreach (MessageReceived message in messageList)
{
foreach (var processor in processors)
{
if (processor.TypeToProcess.Name == message.MessageType)
{
// Now Create an instance of 'processor' from message.MessageBodyAsXML
}
}
}
I tries this:
object messageObject = TextUtility.DeserializeMessage<object>(message.MessageBodyAsXML);
And it kinda works, but the generic 'object' causes problems down stream. I need to be more tightly coupled. I can do this:
Type type = processor.GetType();
And that does populate 'type' with the correct type. But then obviously I can't do this:
type messageObject = TextUtility.DeserializeMessage<type>(message.MessageBodyAsXML);
I am trying hard to avoid a long if/then for each type. Open to ideas. Thanks!
Obviously for such dynamic purposes where you don't know the type at compile-time you will need to provide an overload of your Deserialize method:
public static object Deserialize(Type targetType, string xml)
{
...
}

Can't understand C# Generics

I'm able to understand C# Generics but only when I read about it in a book where the examples are easy to follow. But in real life I get to see complicated C# Generics code like below. Can someone explain to me the generic aspects of this code? I see the type parameter but don't understand why the T is not used in the body of the method. How is the T being used in the body?
public void ValidateExceptionFromResponse<T>( BaseClaimResponseDataContract<T> response )
{
if (response.CommunicationResponseCodes != null && response.CommunicationResponseCodes.Any())
{
var validateResult = new ValidationResults();
foreach (var communicationResponseCodeDataContract in response.CommunicationResponseCodes)
{
validateResult.AddResult( new ValidationResult(communicationResponseCodeDataContract.Description.Current, null, null, null, null));
}
throw FaultManager.GenerateFault(validateResult);
}
if( response.MessageError != null )
{
throw FaultManager.GenerateFault(eErrorCodes.Claims, response.MessageError.Current);
}
}
Here is a snippet for BaseClaimResponseDataContract:
[KnownType(typeof(SummaryClaimsReportResponseDataContract))]
[KnownType(typeof(ClaimResponseDataContract))]
[KnownType(typeof(CommunicationResponseDataContract))]
[DataContract]
public class BaseClaimResponseDataContract<T>
{
[DataMember]
public bool IsRxClaim { get; set; }
[DataMember]
public ThirdPartyDataContract ThirdParty { get; set; }
[DataMember]
public ExternalSystemMessages RequestMessage { get; set; }
[DataMember]
public bool RequestAccepted { get; set; }
[DataMember]
public string ResponseStatus { get; set; }
[DataMember]
[StringLength(10)]
public string ResponseCodes { get; set; }
[DataMember]
public string[] ResponseCodesArray
{
get
{
var lstMessageCodes = new List<string>();
if (!string.IsNullOrEmpty(ResponseCodes))
{
for (int i = 0; i < ResponseCodes.Length / 2; i++)
{
var code = ResponseCodes.Substring(i*2, 2);
if (!string.IsNullOrWhiteSpace(code))
lstMessageCodes.Add(code);
}
}
return lstMessageCodes.ToArray();
}
}
[DataMember]
public IEnumerable<CommunicationResponseCodeDataContract> CommunicationResponseCodes;
[DataMember]
public StringDataContract MessageError { get; set; }
public void CopyFrom(BaseClaimResponseDataContract<T> claimResponse)
{
IsRxClaim = claimResponse.IsRxClaim;
ThirdParty = claimResponse.ThirdParty;
RequestMessage = claimResponse.RequestMessage;
RequestAccepted = claimResponse.RequestAccepted;
ResponseStatus = claimResponse.ResponseStatus;
ResponseCodes = claimResponse.ResponseCodes;
CommunicationResponseCodes = claimResponse.CommunicationResponseCodes;
MessageError = claimResponse.MessageError;
}
}
In this situation, it seems the only purpose of the generic argument is to enforce that the parameter to the method must be a BaseClaimResponseDataContract<T>. I suspect multiple types in your solution inherit from this, for example:
public class SomeSample : BaseClaimResponseDataContract<AnotherClass>
{
}
The method can only be called with instances that implement this base type, so it's like a form of marking classes with an interface.
The method was made generic because it takes a generic argument. In order to specify the type of the argument a generic is used which means the method much take a generic argument itself.
In the case, it's not the method so much that's generic: it's the argument. The method is generic simply so that it can accept a type that is generic. You don't need to use the T argument within the method, because it's enough to know about the BaseClaimResponseDataContract part.
Usually, generics are used to conserve type information and flow it around. You get the same type out of a list that you put in.
In your case that is not apparent. T seems to be unused except to close the generic type.
Maybe BaseClaimResponseDataContract<T> has no useful non-generic base class. You can't use an open generic type, so you have to close it with a generic type parameter.
It doesn't matter whether T is used in the method or not. We can have a generic function like this:
int dummy<T> (List<T> a)
{
return a.Count * 2;
}
As you can see, T is not used anywhere in the method.Your example might also be something like this. Read on if you need more explanation:
Look at it this way: you have a generic type, and you want to write a method which takes a parameter of such a type, here BaseClaimResponseDataContract<>. Now, you can either write different methods, each for a concrete instance of this type, e.g.
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<int> response )
{ ... }
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<float> response )
{ ... }
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<String> response )
{ ... }
which of course in not efficient, or let the method be a generic one, i.e. can take instances of BaseClaimResponseDataContract<> made from all types. Let's call this type T, then we can write
public void ValidateExceptionFromResponse<T>( BaseClaimResponseDataContract<T> response )

Categories

Resources