у меня есть немного проблемы при реализации некоторой логики сериализации/десериализации.
У меня есть несколько классов, что каждый берет другой тип объекта Запроса, все реализующие единый интерфейс и наследовавшийся реализации по умолчанию:
Это - то, как я думаю, что это должно быть:
Запросы:
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); + попытка/выгода и другая Обработка ошибок на неудавшейся десериализации).
Встраивание информации о типе в сериализированные Данные не возможно и не предназначено.
Спасибо за любые Подсказки.
Возможно, я совершенно неправильно понял вопрос, но я просто смотрю на пример кода и комментарии здесь...
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);
Это довольно уродливо, но так оно и есть, когда вы пытаетесь смешать общие типы с отражением.
О, и это предполагает, что "сериализатор" сам является родовым типом; если вы пытаетесь вызвать родовой метод на неродовом типе, как предполагает исходный код, то это становится гораздо более громоздким.