2010-05-10 7 views
1

j'ai un petit problème de la logique mise en œuvre de sérialisation/désérialisation.C#: déterminer le type de (dé) sérialisation

J'ai plusieurs classes qui prennent chacun un autre type d'objet de demande, tout mettant en oeuvre une interface commune et héritant d'une implémentation par défaut:

Voilà comment je pense qu'il devrait être:

Demandes

interface IRequest 
{ 
    public String Action {get;set;} 
} 

class DefaultRequest : IRequest 
{ 
    public String Action {get;set;} 
} 

class LoginRequest : DefaultRequest 
{ 
    public String User {get;set;} 
    public String Pass {get;set;} 
} 

Handlers

interface IHandler<T> 
{ 
    public Type GetRequestType(); 
    public IResponse HandleRequest(IModel model, T request); 
} 

class DefaultHandler<T> : IHandler<T> // Used as fallback if the handler cannot be determined 
{ 
    public Type GetRequestType() 
    { 
    return /* ....... how to get the Type of T? ((new T()).GetType()) ? .......... */ 
    } 

    public IResponse HandleRequest(IModel model, T request) 
    { 
     /* ... */ 
    } 
} 

class LoginHandler : DefaultHandler<LoginRequest> 
{ 
    public IResponse HandleRequest(IModel mode, LoginRequest request) 
    { 
    } 
} 

Appel

class Controller 
{ 
    public ProcessRequest(String action, String serializedRequest) 
    { 
    IHandler handler = GetHandlerForAction(action); 
    IRequest request = serializer.Deserialize<handler.GetRequestType()>(serializedRequest); 
    handler(this.Model, request); 
    } 
} 

Est-ce que je pense même possible?

Ma solution actuelle est que chaque gestionnaire obtient la chaîne sérialisés et lui-même est responsable de désérialisation. Ce n'est pas une bonne solution car elle contient du code dupliqué, le début de chaque méthode HandleRequest est identique (FooRequest request = Deserialize (serializedRequest); + try/catch et autre traitement des erreurs lors de la désérialisation échouée).

Intégration des informations de type dans les données sérialisé est impossible et non prévu.

Merci pour tous les conseils.

Répondre

2

j'ai complètement mal compris la question, mais je ne fais que regarder à l'exemple de code et les commentaires ici ...

public Type GetRequestType() 
{ 
    return /* ....... how to get the Type of T? ((new T()).GetType()) ? */ 
} 

Êtes-vous vraiment juste essayer d'obtenir le type d'exécution du paramètre de type T ? Si c'est le cas, utilisez simplement typeof.

public Type GetRequestType() 
{ 
    return typeof(T); 
} 

Rappelez-vous, je suis à la recherche plus tard, à cet autre code:

class Controller 
{ 
    public ProcessRequest(String action, String serializedRequest) 
    { 
     IHandler handler = GetHandlerForAction(action); 
     IRequest request = 
      serializer.Deserialize<handler.GetRequestType()>(serializedRequest); 
     handler(this.Model, request); 
    } 
} 

Vous ne pouvez pas le faire. Vous ne pouvez pas y coller un Type en tant que paramètre de type générique, il ne sera pas compilé. Si vous avez une exécution Type instance réelle que vous devez utiliser comme un paramètre générique, alors la seule façon de le faire est à la réflexion:

Type serializerDef = typeof(MySerializer<>); 
Type serializerType = serializerDef.MakeGenericType(requestType); 
MethodInfo method = serializerType.GetMethod("Deserialize", 
    BindingFlags.Instance | BindingFlags.Public); 
IRequest request = (IRequest)method.Invoke(serializer, serializedRequest); 

Il est assez laid, mais c'est la façon dont il est quand vous essayez de mélanger les types génériques avec la réflexion.

Oh, et cela suppose que lui-même est un type générique « sérialiseur »; si vous essayez d'appeler une méthode générique sur un type non générique , comme le code d'origine indique, cela devient beaucoup plus lourd.

+0

Ceci est une partie de la solution et aide beaucoup (même si je me sens stupide maintenant parce que je savais typeof(), mais en quelque sorte échoué à se rappeler), mais j'ai encore des problèmes avec la partie appelant. Quoi qu'il en soit, merci pour votre aide, va creuser plus loin dans cette direction. – dbemerlin

+1

Merci encore, semble que je vais devoir chercher une autre façon que j'essaie d'éviter la réflexion, car il blesse généralement la lisibilité et la maintenabilité beaucoup et c'est quelque chose que je me soucie vraiment. – dbemerlin

Questions connexes