I am working on a websocket client application. The server send messages in JSON format and I want to deserialize it. There have one string in the JSON format data that shows the type of message (it has about 50 types today, maybe it will have more in the future).
So I have written a large switch statement like this:
switch(type){
case "type1":
DoSth<T1>(DeserializeFunction<T1>(message));
break;
case "type2":
DoSth<T2>(DeserializeFunction<T2>(message));
break;
//...
}
Is it possible to optimize this statement?
This is the model:
public record EventMessage<T> where T : IEventExtraBody
{
// this will always be 0
[JsonPropertyName("s")]
public int EventType { get; set; }
[JsonPropertyName("sn")]
public long SerialNumber { get; set; }
[JsonPropertyName("d")]
public EventMessageData<T> Data { get; set; }
public override string ToString()
{
return JsonSerializer.Serialize(this);
}
}
public record EventMessageData<T> where T : IEventExtraBody
{
// Some other properties
[JsonPropertyName("extra")]
public EventMessageExtra<T> Extra { get; set; }
}
public record EventMessageExtra<T> where T : IEventExtraBody
{
[JsonPropertyName("type")]
public string Type { get; set; } // this string indicates the type of message
[JsonPropertyName("body")]
public T Body { get; set; }
}
Body (an example):
public record ExitedGuildEvent : IEventExtraBody
{
[JsonPropertyName("user_id")]
public string UserId { get; set; }
[JsonPropertyName("exited_at")]
public long ExitedAt { get; set; }
}
When message arrived, I use JsonDocument to get the type string.
var typeString = JsonDocument.Parse(message.Text).RootElement.GetProperty("d").GetProperty("extra").GetProperty("type").GetString()
Then, I want to deserialize the message and publish it to MessageHub.
Deserializing the json string and publish:
_messageHub.Publish(JsonSerializer.Deserialize<EventMessage<BodyType>>(message.Text));
And because there are lots of BodyType, and EventMessage<Type.GetType("TypeClassPath")>(message.Text) is illegal, I write a large switch statement.
Maybe I have build a very bad model for this situation. I hope you can give me some advice.
You could replace switch-case with a hashmap. To do that you just need to move every case into separate function. Here you can create a factory method to help you to fill out a hashmap because cases are pretty similar
public class YourHub
{
private IMessageHub _messageHub = new MessageHub();
private Dictionary<string, Action<string, IMessageHub>> _methods;
public YourHub()
{
//fill out the hashmap for all types that you have
//make sure this hashmap is shared between operations
_methods = new Dictionary<string, Action<string, IMessageHub>>()
{
{"key1", CreateAction<EventMessage<ExitedGuildEvent>>() }
};
}
//factory method for the actions
private Action<string, IMessageHub> CreateAction<T>()
{
return (json, hub) => hub.Publish(JsonSerializer.Deserialize<T>(json, null));
}
public void ProcessMessage(string json)
{
var typeString = JsonDocument
.Parse(json)
.RootElement.GetProperty("d")
.GetProperty("extra")
.GetProperty("type")
.GetString();
if (!_methods.ContainsKey(typeString)) throw new NotSupportedException();
var method = _methods[typeString];
method(json, _messageHub);
}
}
This aproach won't give you a huge perfomance boost on 50 elements, but it looks cleaner. The runtime complexity is O(1) compared to O(n) with switch-case, but it takes O(n) additional space.
A better solution than a big switch would probably be to refactor DeserializeFunction into an interface and class.
Register It by type and then resolve it. Either with a DI container or by a dictionary where you map.
interface IMessageDeserializer {
object Deserialize(Message message);
}
class Type1Deserializer : IMessageDeserializer {
public object Deserialize(Message message){
// Implementation that returns a Type1
return new Type1(){
};
}
}
// Register your serializers (you can use also a DI container but this is simpler just to show how) in a dictionary, preferably reused
Dictionary<Type, IMessageDeserializer> serializers = new Dictionary<Type, IMessageDeserializer>();
serializers.Add("type1", new Type1Deserializer());
serializers.Add("type2", new Type2Deserializer());
serializers.Add("type3", new Type3Deserializer());
// When you need it, use it like this:
string type = "type1"; // This is from your other code
var message = GetMessage(); // This is from your other code
IMessageDeserializer serializer = serializers[type];
object deserializedMessage = serializer.Deserialize(message);
// To create your event message, either add a constraint to the T of IMessageDeserializer so you can pass it into another function that creates the event message or just simply return the messagehub message as json directly from your IMessageDeserializer implementation)
(I wrote this from memory so I apologise for any mistakes)
Related
I have a converter class that receives json in input, here are 2 valid examples:
{
"method": "Model",
"payload": {
"key": "value"
}
}
and
{
"method": "OtherModel",
"payload": {
"foo": "bar"
}
}
In C#, I have classes mapped to each possible model:
public class Model
{
public string Key { get; set; }
}
public class OtherModel
{
public string Foo { get; set; }
}
I need a generic converter
How can I use the string value in the method of the JSON to convert in a generic way the content of the payload field?
Is using a huge switch the only way? This is the prototype I have so far but there are hundreds of different models so it will grow quite large...
public IResult ParseJson(string json)
{
Regex regexMessageName = new Regex("\"messageName\": \"(.*?)\"", RegexOptions.Compiled);
var messageName = regexMessageName.Match(json).Groups[1].Value;
switch (messageName)
{
case "Model":
var raw = JsonConvert.DeserializeObject<JsonData<Model>>(json);
return new LogInfoRequestResult<Model> { Raw = raw };
case "OtherModel":
var raw = JsonConvert.DeserializeObject<JsonData<OtherModel>>(json);
return new LogInfoRequestResult<OtherModel> { Raw = raw };
}
}
If you want complete control of your classes, and allow them to evolve independently, then you can have one base class that owns the Method, and then as many subclasses as you want with their own definition of the payload.
First, parse into the baseclass, just to get a strongly typed deserialization of Method
Then, there are a lot of patterns to address branching logic.
If you have 1-2 cases, an if statement is fine
If you have 3-5 cases, you can use a switch
If you have 6-10 cases, you can create a dictionary that maps method name to class type
If you have more than that, you can use the strategy pattern and pass an interface around
Here's an example of how you could write the code:
var json = #"{
'method': 'Model',
'payload': {
'key': 'value'
}
}";
var modelBase = JsonConvert.DeserializeObject<ModelBase>(json);
var methodMapping = new Dictionary<string, Type>()
{
{MethodTypes.Model.ToString(), typeof(Model)},
{MethodTypes.OtherModel.ToString(), typeof(OtherModel)},
};
Type methodClass = methodMapping[modelBase.Method];
var result = JsonConvert.DeserializeObject(json, methodClass);
Note: Since we're programmatically determining the correct type, it's hard to pass to a generic <T>, so this uses the overload of DeserializeObject that takes type as a param
And here are the classes that model incoming messages
public enum MethodTypes
{
Model,
OtherModel
}
public class ModelBase
{
public string Method { get; set; }
}
public class Model : ModelBase
{
public ModelInfo Payload { get; set; }
public class ModelInfo
{
public string Key { get; set; }
}
}
public class OtherModel : ModelBase
{
public ModelInfo Payload { get; set; }
public class ModelInfo
{
public string Foo { get; set; }
}
}
Dictionary<string,string>
If your data is always going to be "foo":"bar" or "key":"value" .... string:string, then Cid's suggesting to use Dictionary<string,string> Payload makes a lot of sense. Then figure out however you want to map from that c# class in a c# constructor that returns whatever type you want.
Additional Resources:
How to handle both a single item and an array for the same property using JSON.net
Deserializing polymorphic json classes without type information using json.net
JSON.NET - Conditional Type Deserialization
Conditionally deserialize JSON string or array property to C# object using JSON.NET?
You can instanciate an object of the expected class using Activator.CreateInstance(), then populate it with JsonConvert.PopulateObject()
In example :
Type t = Type.GetType($"NameSpaceName.{messageName}"); // this must be a fully qualified name
object obj = Activator.CreateInstance(t);
JsonConvert.PopulateObject(json, obj);
LogEvent represents information like log level, message, user, process name, ...
Some of these properties' values require pretty much effort for generation, e. g. the process name. Those properties' generated values are usually not changed, BUT despite this fact it should be possible to change them.
I considered the prototype pattern starting with a protoype, whose generic properties are pre-allocated. The protoype stays the same object during the lifetime of the application, but its properties' values might change as described above. New LogEvent objects should use the current prototype's values, objects created before the change should continue using the old values, that means, referencing the prototype from the "real" LogEvent object is not an option.
However the "real" LogEvent requires some properties to be not null, whereas this requirement is not useful for the prototype. I would like to prevent invalid objects of LogEvent. However if I use usual protoype pattern I would have to add a constructor to create the prototype, but this constructor would not create a valid object and I want to avoid, that an invalid object (the prototype itself or a clone of it) is used accidentally.
I spent some time on searching a solution, but the approaches listed below are pretty ugly. I hope, that there is an elegant solution. Meanwhile I tend to option 3, because 1 and 2 do not seem to be clean.
General structure
public interface ILogEvent
{
string PreAllocatedProperty1 { get; set; }
string PreAllocatedProperty2 { get; set; }
string IndividualProperty1 { get; set; }
string IndividualProperty2 { get; set; }
}
Option 1
Pros
LogEventPrototype can not be used as ILogEvent.
properties do not have to be declared in multiple classes
Cons
properties have to be mapped manually
static methods => interface for prototypes not possible
Code
class LogEventPrototype
{
public string PreAllocatedProperty1 { get; set; }
public string PreAllocatedProperty2 { get; set; }
public string IndividualProperty1 { get; set; }
public string IndividualProperty2 { get; set; }
public LogEventPrototype() { GeneratePreAllocatedProperties(); }
private void GeneratePreAllocatedProperties()
{
// if you invoke the helper functions later again,
// they might return different results (e. g.: user identity, ...)
PreAllocatedProperty1 = Helper.ComplexFunction();
PreAllocatedProperty2 = Helper.AnotherComplexFunction();
}
}
class LogEvent : LogEventPrototype, ILogEvent
{
// just for creating the prototype, object will be in an INVALID state
private LogEvent() : base() { }
// object will be in a VALID state
public LogEvent(string individualProperty2)
: this()
{
if (individualProperty2 == null)
throw new ArgumentNullException();
IndividualProperty2 = individualProperty2;
}
public static LogEvent FromPrototype(LogEventPrototype prototype)
{
// clone manually
return new LogEvent(prototype.IndividualProperty2)
{
IndividualProperty1 = prototype.IndividualProperty1,
PreAllocatedProperty1 = prototype.PreAllocatedProperty1,
PreAllocatedProperty2 = prototype.PreAllocatedProperty2
};
}
}
Option 2
Similar to option 1, but:
Pros
it is "ensured", that LogEventPrototype is never instantiated, it is just used as return type
no manual mapping
Cons: It seems to be hacky.
class LogEventPrototype
{
// properties ... (same as in option 1)
protected LogEventPrototype()
{
GeneratePreAllocatedProperties();
}
}
class LogEvent : LogEventPrototype, ILogEvent
{
// constructors same as in option 1; FromPrototype() removed
public static LogEventPrototype CreateProtoype()
{
return new LogEvent();
}
public static LogEvent FromPrototype(LogEventPrototype prototype)
{
if(prototype.IndividualProperty2 == null)
throw new ArgumentException();
return (LogEvent)prototype;
}
public static LogEventPrototype CreateProtoype()
{
return new LogEvent();
}
}
Option 3
Do not use a dedicated class for prototypes, but make the LogEvent constructor public and risk invalid LogEvent objects. Use a Validate() method instead and hope, that a client does not forget to use it.
How would I deserialize YAML to a immutable data structure?
e.g. I have this YAML:
Value: SomeString
Number: 99
And this data structure:
public class MyData
{
public MyData(string value, int number)
{
Value = value;
Number = number;
}
public string Value { get; }
public int Number { get; }
}
For this I'd to use the constructor. So somehow I'd need to first retrieve a Dictionary<string, object> parsed from the YAML respecting my class (so 99 would be int, not string), then scan my type for an appropriate constructor,
Although the question doesn't mention it, I'm assuming you are using YamlDotNet (or SharpYaml which is a fork of YamlDotNet)
YamlDotNet doesnt support deserializing into classes that do not have a default constructor - but one option to achieve what you want is to deserialize into an intermediate Builder type that is mutable which can produce the final type.
e.g.
public class MyDataBuilder
{
public string Value { get; set; }
public int Number { get; set; }
public MyData Build() => new MyData(Value, Number);
}
And then use something like:
deserializer.Deserialize<MyDataBuilder>(yaml).Build();
You would end up having to create a parallel set of builders for your whole model however, e.g. if MyData had a third parameter of type MyOtherData (I've changed the example to use records instead of classes to make it concise):
public record MyOtherData(string OtherValue);
public record MyData(string Value, int Number, MyOtherData otherData);
In which case we would need another Builder:
public class MyOtherDataBuilder
{
public string OtherValue { get; set; }
}
And MyDataBuilder would look like:
public class MyDataBuilder
{
public string Value { get; set; }
public int Number { get; set; }
public MyOtherDataBuilder MyOtherData { get; set; }
public MyData Build() => new MyData(Value, Number, MyOtherData.Build());
}
It's an old but surprisingly relevant question. Now, with records in C#, immutable collections in .net, lack of ability to deserialize immutable data is a blocker - there is no way we need to change all our data types just to be able to deserialize. One practical workaround that I found - is to convert yaml to json first, then deal with json your preferred way - System.Text.Json, Newtonsoft, etc.
Here is how to do is easiest way:
static string ConvertToJson(string yaml) {
object DeserializeYaml() =>
new DeserializerBuilder()
.Build()
.Deserialize(new StringReader(yaml))
?? throw new InvalidOperationException("Cannot deserialize yaml string:" + Environment.NewLine + yaml);
string SerializeYamlObjectToJson(object yamlObject) =>
new SerializerBuilder()
.JsonCompatible()
.Build()
.Serialize(yamlObject);
return SerializeYamlObjectToJson(DeserializeYaml());
}
The only disadvantage, potentially big, is performance. I feel, however, that it's rarely an important requirement for yaml.
use the FormatterServices.GetUninitializedObject API (this will NOT invoke any constructors at all) and then use reflection to set fields.
Code example:
var instance = FormatterServices.GetUninitializedObject(typeof(MyData));
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
var type = typeof(MyData);
var stringField = type.GetField("_value", flags);
stringField.SetValue(instance, "SomeString");
var numberField = type.GetField("_number", flags);
numberField.SetValue(instance, 99);
MyData data = (MyData)instance;
I am trying to use generics on a List property for a class.
Basically I am using a message based service that would receive a collection of Message Requests. For each Message Request received, I would return a corresponding Message Response.
So my implementation would look something like this:
public class MessageRequest
{
private string _messageId;
private string _serviceMethod;
public MessageRequest(string id, string operation)
{
_messageId = MessageId;
_serviceMethod = operation;
}
public string MessageId { get { return _messageId; } }
public string ServiceMethod { get { return _serviceMethod; } }
}
public class MessageResponse
{
private List<T> _data; <--This does't Work..
private string _messageId;
public string MessageId { get { return _messageId; }}
public List<T> Data { get { return _data; }}
}
public List<MessageResponse> GetData(List<MessageRequest> requests)
{
List<MesssageResponse> responses = new List<MessageResponse>();
foreach(MessageRequest r in requests)
{
//I will determine the collection type for the response at runtime based
//on the MessageRequest "ServiceMethod"
List<TypeIFiguredOutFromServiceMethod> data = getData();
responses.add(new MessageResponse()
{
MessageId = r.MessageId,
Data<TypeIFiguredOutFromServiceMethod> = data
});
Something like that...
I can't specify the List Type on the MessageResponse class that is this:
public class MessageResponse<T>
{
}
because the collection of MessageRequests will have different operations and thus will require different collection results.
Since you are dealing with messages that most likely come in as strings that you need to parse anyway, I would be inclined to keep them as strings like this:
public class MessageResponse
{
public string MessageId { get; private set; }
public Type MessageType { get; private set; }
public List<string> Data { get; private set; }
}
If your code has already performed the parsing then change string to object and go with that.
As it would turn out this topic has been talked about a few times on SO. I am going to post what I did so hopefully someone can benefit from this (or even someone gives me a better way of accomplishing this).
The intent of my implementation was to pass into a Service Manager object a collection of request objects; with each request object specifying an Operation and any additional parameters required for that operation.
My service implementation would then fetch a response for each request object received - the response data would vary in type - the determinant being the operation specified in the request. That is if I have an operation that is "GetCatalog", the result from that request would be a List<Items>. Conversely a "GetAddressbooks" would yield List<AddressbookRecords>.
This is where I needed a generic property on a class. My Message response object would have a generic List as a property.
In the end I ended up using a combination of #Mihai Caracostea suggestion to use object and the solution posted here.
First I modified the MessageRequest and MessageResponse objects both for clarity and efficiency:
public class MessageRequest
{
private readonly string _messageId;
private readonly Operation _operation;
public MessageRequest(string id, Operation operation)
{
_messageId = id;
_operation = operation;
}
public string MessageId { get { return _messageId; } }
public Operation Operation { get { return _operation; } }
}
public class MessageResponse
{
private object _data;
public MessageRequest Request { get; set; }
public T Data<T>()
{
return (T)Convert.ChangeType(_data, typeof(T));
}
public void SetData(object data)
{
_data = data;
}
}
The MessageResponse definition really enables this. Using the getter / setter approach to the property - I use the Object _data field to set the data received from a backing service and the T Data to basically cast the data to what it should be when the client receiving the MessageResponse object reads the data.
So the Service Manager Implementation looks like this:
public List<MessageResponse> GetData(List<MessageRequest> messageRequests)
{
List<MessageResponse> responses = new List<MessageResponse>();
try
{
foreach (MessageRequest request in messageRequests)
{
//Set up the proxy for the right endpoint
SetEndpoint(request);
//instantiate a new Integration Request with the right proxy and program settings
_ir = new IntegrationRequest(_proxy, ConfigureSettings(request));
MessageResponse mr = new MessageResponse { Request = request };
using (IntegrationManager im = new IntegrationManager(_ir))
{
mr.SetData(GetData(im, request));
}
responses.Add(mr);
}
return responses;
}//
catch (Exception)
{
throw;
}
The client implementation consuming the result of the GetData method looks like:
List<MessageRequest> requests = new List<MessageRequest>();
requests.Add(new MessageRequest(Guid.NewGuid().ToString(), Operation.GetBudgets));
requests.Add(new MessageRequest(Guid.NewGuid().ToString(), Operation.GetCatalogItems));
List<MessageResponse> responses;
using (ServiceManager sm = new ServiceManager())
{
responses = sm.GetData(requests);
}
if (responses != null)
{
foreach (var response in responses)
{
switch (response.Request.Operation)
{
case Operation.GetBudgets:
List<Budget> budgets = response.Data<List<Budget>>();
break;
case Operation.GetCatalogItems:
List<Item> items = response.Data<List<Item>>();
break;
}
}
}
This is just a test - but basically I constructed two MessageRequest objects (get budgets, and get catalog items) - posted to the Service and a collection of the MessageResponse objects returned.
This works for what I need it to do.
Two additional points I want to mention on this subject are one I looked a using reflection to to determine the response types at runtime. The way I was able to to do it was by specifying a custom attribute type on the operation enum:
public enum Operation
{
[DA.Services.ResponseType (Type = ResponseType.CreateOrder)]
CreateOrder,
[DA.Services.ResponseType(Type = ResponseType.GetAddressbooks)]
GetAddressbooks,
[DA.Services.ResponseType(Type = ResponseType.GetCatalogItems)]
GetCatalogItems,
[DA.Services.ResponseType(Type = ResponseType.GetAddressbookAssociations)]
GetAddressbookAssociations,
[DA.Services.ResponseType(Type = ResponseType.GetBudgets)]
GetBudgets,
[DA.Services.ResponseType(Type = ResponseType.GetUDCTable)]
GetUDCTable
}
class ResponseType : System.Attribute
{
public string Type { get; set; }
public const string CreateOrder = "Models.Order";
public const string GetAddressbooks = "Models.AddressbookRecord";
public const string GetCatalogItems = "Models.Item";
public const string GetAddressbookAssociations = "Models.AddressbookAssociation";
public const string GetBudgets = "Models.Budget";
public const string GetUDCTable = "Models.UdcTable";
}
I basically looked at using Activator.CreateType() to dynamically create the response object for the client by evaluating the ResponseType.Type on the operation specified in the request.
While this was elegant - I found it was not worth the time expense to process. This implementation has fairly well defined objects that haven't changed in years. I am willing to write a switch statement to cover all scenarios rather than using reflection for the flexibility. The reality is I just don't need the flexibility in this particular instance.
The second point I want to mention (just for anyone that reads this) edification is "Why" a generic cannot be used as a class property. As it would turn out this was also debated. There were arguments that went from "it doesn't make sense" to "microsoft felt it was too hard to do in the release and abandoned it". Those discussions can be found here and here.
In the end one of those threads provided a link to a technical reason. That reason being the compiler would have no way of determining how much memory to allocate for an object that has a generic property. The author of the article was Julian Bucknail and can be found here.
Thank you to everyone that posted suggestions in finding my solution.
EDIT I updated my question for completeness.
I have incoming REST calls from an iPHone client. It is meant to consume type-specific objects
in response to generic requests. For example:
http://localhost:81/dashboard/group/id/0
returns data from the Regions type
http://localhost:81/dashboard/group/id/1
returns data from the Customers type
http://localhost:81/dashboard/group/id/2
returns data from the Users type
and so on.
The WCF Dashboard.svc service exposes a base method GetGroupById
which I use to determine and return the type-specific response:
public class Dashboard : GroupBase, Contracts.IDashboardService
{
private string name = String.Empty;
public Dashboard() : base()
{
if (!ServiceSecurityContext.Current.PrimaryIdentity.IsAuthenticated)
throw new WebException("Unauthorized: Class: Dashboard, Method: Dashboard()",
System.Net.HttpStatusCode.Forbidden);
name = ServiceSecurityContext.Current.PrimaryIdentity.Name;
}
public override System.IO.Stream GetGroupById(string id)
{
return base.GetGroupById(id);
}
}
Now, inside my abstract base class the GetGroupById has a switch/case statement that populates
and returns unique data transfer objects based on the corresponding groupid parameter:
public abstract class GroupBase
{
protected GroupBase () { }
public virtual Stream GetGroupById(string id)
{
// I have tried assigning response to null or, in this case,
// assigning it to a random service object. I have also tried
// IObjectFactory response; The last fails at compile-time and
// the other two always produce null
IObjectFactory response =
ObjectFactory<IObjectFactory, UserService>.Create();
var groupId = System.Convert.ToInt32(id);
var serializer = new JavaScriptSerializer();
byte[] bytes = null;
var message = String.Empty;
try
{
switch (groupId)
{
case 0: // regions
response = ObjectFactory<IObjectFactory, RegionService>.Create();
break;
case 1: // customers
response = ObjectFactory<IObjectFactory, CustomerService>.Create();
break;
case 2: // users
response = ObjectFactory<IObjectFactory, UserService>.Create();
break;
}
}
catch (EngageException oops)
{
message = oops.Message;
}
bytes = Encoding.UTF8.GetBytes(serializer.Serialize(response));
return new MemoryStream(bytes);
}
}
A customer ObjectFactory class is used to create the type-specific object:
public static class ObjectFactory where T : F, new()
{
public static F Create()
{
return new T();
}
}
WHERE I AM HAVING PROBLEMS IS what is going on under the hood of my ObjectFactory. I am always
getting ** null ** back. For example, consider the following REST HTTP GET:
http://localhost:81/dashboard/group/id/2
The above command is asking for a JSON string of all Users in the database. Accordingly, the
UserService class is passed into the ObjectFactory method.
public class UserService : IObjectFactory
{
DomainObjectsDto IObjectFactory.Children
{
get
{
return new Contracts.DomainObjectsDto(UserRepository
.GetAllUsers().Select
(p => new Contracts.DomainObjectDto
{
Title = GroupTypes.Customer.ToString(),
Id = p.CustomerId.ToString(),
Type = p.GetType().ToString()
}));
}
}
string IObjectFactory.Method
{
get;
set;
}
string IObjectFactory.Status
{
get;
set;
}
etc...
And, the readonly Get property gets data from the UserRepository, populates the Data Transfer Object
(illustrated below)
[DataContract]
public class DomainObjectDto
{
[DataMember]
public string Title { get; set; }
[DataMember]
public string Id { get; set; }
[DataMember]
public string Type { get; set; }
}
[CollectionDataContract]
public class DomainObjectsDto : List<DomainObjectDto>
{
public DomainObjectsDto() { }
public DomainObjectsDto(IEnumerable<DomainObjectDto> source) : base(source) { }
}
And should return the serialized JSON string of User data to the client. But, my generic type T in my object factory class is always null:
public static F Create()
{
return new T(); // <-- always null!
}
Any ideas??
Hard to tell without seeing the invocation of your factory in context, but my gut feel is that groupId is not in the switch range and thus you are getting the null you defaulted it to. I would add a default case and throw an out of range exception and see if that's your problem.
It's a good idea to add default cases to your switch statements, like:
default:
throw new Exception( "groupId " + groupId + " not found" );
Change the line IObjectFactory response = null; to remove the default, i.e. IObjectFactory response;. Now the compiler will tell you if there is a branch that doesn't assign it (of course, it can't tell you if you assign to null somehow). Note also that there are at least 2 ways of getting null from a new (etc), but these are edge cases - I doubt they are contributing (mentioned for completeness only).