Десериализовать тип интерфейса

У меня есть клиент-серверное приложение, в котором я хочу отправить зашифрованный объект с сервера клиенту.

Клиент отправляет серверу запрос, например:

byte[] encryptedResponse = authenticationService.SendRequest(sessionId, requestData);

Затем клиент получает зашифрованный массив байтов ответа. Затем он звонит

byte[] clearResponse = Cryptography.DecryptSymmetric(key, iv, encryptedResponse);

В clearResponse теперь есть очищенный двоично-сериализованный объект с сервера.

Клиент и сервер совместно используют интерфейсную библиотеку, которая содержит интерфейс IUser, который выглядит так:

public interface IUser : ISerializable
{
   Guid UserId { get; }
   string Username { get; }
} 

Сервер содержит реализацию этого интерфейса, которая выглядит так:

[Serializable]
    internal class User : IUser
    {
        public User(){}

        public User(SerializationInfo info, StreamingContext context)
        {
            Id = Guid.Parse(info.GetString(XmlNodes.UserId));
            Username = info.GetString(XmlNodes.Username);
        }

        public Guid Id { get; set; }

        public string Username { get; set; }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(XmlNodes.UserId, Id.ToString());
            info.AddValue(XmlNodes.Username, Username);            
        }
    }

Сервер использует следующий код для сериализации пользователя для клиента:

byte[] responseData;
IUser user = new User { Id = Guid.NewGuid(), Username = "Dummy" };
using(MemoryStream memoryStream = new MemoryStream())
{
  BinaryFormatter binaryFormatter = new BinaryFormatter();
  binaryFormatter.Serialize(memoryStream, user);
  responseData = memoryStream.ToArray();
}
// encrypt the responseData and send it to the client.

Теперь, если я попытаюсь десериализовать пользователя с помощью:

using(MemoryStream memoryStream = new MemoryStream(clearResponse))
{
  BinaryFormatter binaryFormatter = new BinaryFormatter();
  IUser user = (IUser)binaryFormatter.Deserialize(memoryStream)
}

У меня исключение.

Необработанное исключение типа System.Runtime.Serialization.SerializationException произошло в mscorlib.dll

Дополнительная информация: Сборка «Пользователи, Версия = 1.0.0.0, Культура = нейтральная, PublicKeyToken = null» не может быть найдена.

Как я могу десериализовать тип, в котором я знаю только интерфейс?


person Tomtom    schedule 13.05.2014    source источник


Ответы (1)


Используя BinaryFormatter, вы не можете, поскольку тип является частью данных.

Вы можете использовать XmlSerializer и отправить полученный string как (возможно, зашифрованный) byte[] клиенту. Затем клиенту нужен только «совместимый тип» для его десериализации.

Если вы хотите придерживаться BinaryFormatter, вы также можете переместить тип User в общую библиотеку (если еще не сделали) и сослаться на него сервером и клиентом.

person Christoph Fink    schedule 13.05.2014
comment
В этом ответе говорится, что вы можете, возможно, OP просто не имеет ссылки на сборку, в которой определен тип User. Если он это добавит (как вы сказали в последнем абзаце), код, вероятно, начнет работать нормально. - person oleksii; 13.05.2014
comment
@oleksii: Не совсем: This means that when the binary formatter **deserializes the object it knows its type**, builds the correct object and you can then cast that to an interface type that object implements. и в этом приведении он НЕ знает тип ... - person Christoph Fink; 13.05.2014
comment
да. У меня нет ссылки на сборку, в которой определен пользовательский тип. Но моему клиенту не разрешено знать эту сборку. Есть ли другой способ отправить клиенту тип интерфейса как byte []? - person Tomtom; 13.05.2014
comment
Я знаю только об использовании XmlSerializer. В чем ваша проблема с таким подходом? - person Christoph Fink; 13.05.2014