C#: определите тип для (De-) сериализация

у меня есть немного проблемы при реализации некоторой логики сериализации/десериализации.

У меня есть несколько классов, что каждый берет другой тип объекта Запроса, все реализующие единый интерфейс и наследовавшийся реализации по умолчанию:

Это - то, как я думаю, что это должно быть:

Запросы:

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;} 
}

Обработчики

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)
  {
  }
}

Вызов

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

То, о чем я думаю даже возможный?

Мое текущее Решение состоит в том, что каждый обработчик получает сериализированную Строку и самостоятельно ответственен за десериализацию. Это не хорошее решение, поскольку оно содержит дублирующий код, начало каждого метода HandleRequest выглядит одинаково (запрос FooRequest = Десериализовывают (serializedRequest); + попытка/выгода и другая Обработка ошибок на неудавшейся десериализации).

Встраивание информации о типе в сериализированные Данные не возможно и не предназначено.

Спасибо за любые Подсказки.

1
задан Morfildur 10 May 2010 в 19:12
поделиться

1 ответ

Возможно, я совершенно неправильно понял вопрос, но я просто смотрю на пример кода и комментарии здесь...

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

Вы действительно просто пытаетесь получить тип времени выполнения параметра типа T? Если да, то просто используйте typeof.

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

Учтите, я смотрю позже на этот другой код:

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

Вы не можете этого сделать. Вы не можете просто вставить Type в качестве параметра общего типа, это не скомпилируется. Если у вас есть реальный экземпляр Type во время выполнения, который нужно использовать в качестве общего параметра, то единственный способ сделать это - отражение:

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);

Это довольно уродливо, но так оно и есть, когда вы пытаетесь смешать общие типы с отражением.

О, и это предполагает, что "сериализатор" сам является родовым типом; если вы пытаетесь вызвать родовой метод на неродовом типе, как предполагает исходный код, то это становится гораздо более громоздким.

2
ответ дан 3 September 2019 в 00:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: