Поделиться через


Варианты использования строковых идентификаторов в пакетах SDK для связи

В этой статье рассмотрены варианты использования строки (необработанного идентификатора) в качестве типа представления данных для типа CommunicationIdentifier в SDK-службах связи Azure. Следуйте этим рекомендациям, чтобы понять некоторые варианты использования, когда вы могли бы выбрать «сырой идентификатор» вместо производных от CommunicationIdentifier типов.

Сценарии выбора идентификатора

Обычной задачей при реализации сценариев обмена данными является определение участников бесед. При использовании SDK служб коммуникации CommunicationIdentifier можно однозначно идентифицировать этих участников.

Использование CommunicationIdentifier имеет следующие преимущества:

  • Обеспечивает хорошее автодополнение в средах разработки.
  • Позволяет использовать вариант переключения по типу для решения различных потоков приложений.
  • Позволяет ограничить обмен данными определенными типами.
  • Позволяет получить доступ к сведениям об идентификаторе и использовать их для вызова других API (таких как API Microsoft Graph), чтобы обеспечить широкий интерфейс взаимодействия для участников связи.

Кроме того, CommunicationIdentifier и производные типы (MicrosoftTeamsUserIdentifier, PhoneNumberIdentifier и т. д.) можно преобразовать в их строковое представление (необработанный идентификатор) и восстановить из строки, что упрощает реализацию следующих сценариев:

  • Храните идентификаторы в базе данных и используйте их в качестве ключей.
  • Используйте идентификаторы в качестве ключей в словарях.
  • Реализуйте интуитивно понятные CRUD API REST, используя идентификаторы в качестве ключа в путях API REST, вместо того чтобы полагаться на данные POST.
  • Используйте идентификаторы в качестве ключей в декларативных платформах пользовательского интерфейса, таких как React, чтобы избежать необходимости повторной отрисовки.

Создание CommunicationIdentifier и получение исходного идентификатора

Вы можете создать CommunicationIdentifier из необработанного идентификатора. Вы можете получить сырой идентификатор из типа, производного от CommunicationIdentifier. Он удаляет необходимость в пользовательских методах сериализации, которые могут принимать только определенные свойства объекта и опустить другие. Например, MicrosoftTeamsUserIdentifier имеет несколько свойств, таких как IsAnonymous или Cloud методы для получения этих значений (в зависимости от платформы). Использование методов, предоставляемых Communication Identity SDK, гарантирует, что способ сериализации идентификаторов остается каноническим и согласованным, даже при добавлении новых свойств.

Получение исходного идентификатора из CommunicationUserIdentifier:

public async Task GetRawId()
{
    ChatMessage message = await ChatThreadClient.GetMessageAsync("678f26ef0c");
    CommunicationIdentifier communicationIdentifier = message.Sender;
    String rawId = communicationIdentifier.RawId;
}

Создайте экземпляр CommunicationUserIdentifier из необработанного идентификатора:

public void CommunicationIdentifierFromGetRawId()
{
    String rawId = "8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130";
    CommunicationIdentifier communicationIdentifier = CommunicationIdentifier.FromRawId(rawId);
}

Дополнительные примеры для конкретной платформы см. в следующей статье. Общие сведения о типах идентификаторов

Хранение CommunicationIdentifier в базе данных

Одно из типичных заданий, которые могут потребоваться от вас, заключается в сопоставлении пользователей Служб коммуникации Azure с пользователями, поступающими из базы данных пользователей Contoso или поставщика удостоверений. Обычно этого сопоставления можно добиться, добавив дополнительный столбец или поле в базу данных пользователей Contoso или используя провайдера удостоверений. Однако учитывая характеристики необработанного идентификатора (стабильного, глобально уникального и детерминированного), его можно использовать в качестве первичного ключа для хранилища пользователей.

Предположим, что ContosoUser — это класс, представляющий пользователя вашего приложения, и вы хотите сохранить его вместе с соответствующим CommunicationIdentifier в базе данных. Исходное значение для CommunicationIdentifier может поступать из API коммуникационной идентификации, вызовов или чатов, или из API Contoso, и независимо от базового типа может быть представлено как string тип данных в вашем языке программирования.

public class ContosoUser
{
    public string Name { get; set; }
    public string Email { get; set; }
    public string CommunicationId { get; set; }
}

Вы можете получить доступ к свойству RawId элемента CommunicationId для получения строки, которую можно сохранить в базе данных.

public void StoreToDatabase()
{
    CommunicationIdentifier communicationIdentifier;

    ContosoUser user = new ContosoUser()
    {
        Name = "John",
        Email = "[email protected]",
        CommunicationId = communicationIdentifier.RawId
    };
    SaveToDb(user);
}

Если вы хотите получить CommunicationIdentifier из сохраненного необработанного идентификатора, необходимо передать необработанную строку методу FromRawId() :

public void GetFromDatabase()
{
    ContosoUser user = GetFromDb("[email protected]");
    CommunicationIdentifier communicationIdentifier = CommunicationIdentifier.FromRawId(user.CommunicationId);
}

Он возвращает CommunicationUserIdentifier, PhoneNumberIdentifierMicrosoftTeamsUserIdentifierили UnknownIdentifier на основе типа идентификатора.

Хранение CommunicationIdentifier в коллекциях

Если сценарий требует работы с несколькими CommunicationIdentifier объектами в памяти, их может потребоваться сохранить в коллекции (словарь, список, хэш-набор и т. д.). Коллекция полезна, например для поддержания списка участников звонка или чата. Так как логика хэширования зависит от значения необработанного идентификатора, можно использовать CommunicationIdentifier в коллекциях, требующих наличия надежного хэширования элементов.

В следующих примерах показано, как добавить CommunicationIdentifier объекты в различные типы коллекций и проверить, находятся ли они в коллекции, создавая новые идентификаторы из значения исходного идентификатора.

В следующем примере показано, как использовать необработанный идентификатор в качестве ключа в словаре для хранения сообщений пользователей:

public void StoreMessagesForContosoUsers()
{
    var communicationUser = new CommunicationUserIdentifier("8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130");
    var teamsUserUser = new CommunicationUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130");
    
    // A dictionary with a CommunicationIdentifier as key might be used to store messages of a user.
    var userMessages = new Dictionary<string, List<Message>>
    {
        { communicationUser.RawId, new List<Message>() },
        { teamsUserUser.RawId, new List<Message>() },
    };

    // Retrieve messages for a user based on their Raw ID.
    var messages = userMessages[communicationUser.RawId];
}

Так как логика хэширования зависит от значения Raw ID, вы можете использовать CommunicationIdentifier непосредственно в качестве ключа в словаре.

public void StoreMessagesForContosoUsers()
{
    // A dictionary with a CommunicationIdentifier as key might be used to store messages of a user.
    var userMessages = new Dictionary<CommunicationIdentifier, List<Message>>
    {
        { new CommunicationUserIdentifier("8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130"), new List<Message>() },
        { new MicrosoftTeamsUserIdentifier("45ab2481-1c1c-4005-be24-0ffb879b1130"), new List<Message>() },
    };

    // Retrieve messages for a user based on their Raw ID.
    var messages = userMessages[CommunicationIdentifier.FromRawId("8:acs:bbbcbc1e-9f06-482a-b5d8-20e3f26ef0cd_45ab2481-1c1c-4005-be24-0ffb879b1130")];
}

Логика хэширования, которая зависит от значения необработанного идентификатора, также позволяет добавлять CommunicationIdentifier объекты в хэш-наборы:

public void StoreUniqueContosoUsers()
{
    // A hash set of unique users of a Contoso application.
    var users = new HashSet<CommunicationIdentifier>
    {
        new PhoneNumberIdentifier("+14255550123"),
        new UnknownIdentifier("28:45ab2481-1c1c-4005-be24-0ffb879b1130")
    };

    // Implement custom flow for a new communication user.
     if (users.Contains(CommunicationIdentifier.FromRawId("4:+14255550123"))){
        //...
     }
}

Другим вариантом использования является использование необработанных идентификаторов в мобильных приложениях для идентификации участников. Вы можете внедрить данные представления участников для удаленного участника, если вы хотите локально обрабатывать эти сведения в библиотеке пользовательского интерфейса, не отправляя их в службы коммуникации Azure.

Эти данные представления могут содержать UIImage, представляющий аватар для визуализации, и отображаемое имя, которое они могут использовать вместо изображения.

Идентификатор CommunicationIdentifier и необработанный идентификатор, полученные из него, можно использовать для однозначной идентификации удаленного участника.

callComposite.events.onRemoteParticipantJoined = { identifiers in
  for identifier in identifiers {
    // map identifier to displayName
    let participantViewData = ParticipantViewData(displayName: "<DISPLAY_NAME>")
    callComposite.set(remoteParticipantViewData: participantViewData,
                      for: identifier) { result in
      switch result {
      case .success:
        print("Set participant view data succeeded")
      case .failure(let error):
        print("Set participant view data failed with \(error)")
      }
    }
  }
}    

Использование необработанного идентификатора в качестве ключа в путях REST API

При разработке REST API можно создавать конечные точки, которые принимают либо CommunicationIdentifier, либо строку необработанного идентификатора. Если идентификатор состоит из нескольких частей (например, ObjectID, имя облака и т. д.), и вы используете MicrosoftTeamsUserIdentifier, может потребоваться передать его в тело запроса. Однако использование Raw ID позволяет обращаться к сущности в пути URL-адреса вместо передачи всего составного объекта в формате JSON в теле сообщения. Таким образом, у вас будет более интуитивно понятный CRUD API REST.

public async Task UseIdentifierInPath()
{
    CommunicationIdentifier user = GetFromDb("[email protected]");
    
    using HttpResponseMessage response = await client.GetAsync($"https://contoso.com/v1.0/users/{user.RawId}/profile");
    response.EnsureSuccessStatusCode();
}

Извлечение сведений об идентификаторах из необработанных идентификаторов.

Согласованный базовый необработанный идентификатор включает:

  • Десериализация в нужный тип идентификатора (на основе которого можно настроить поток вашего приложения).
  • Извлечение сведений об идентификаторах (например, об идентификаторе oid для MicrosoftTeamsUserIdentifier).

В примере показаны оба преимущества:

  • Тип позволяет решить, откуда берется аватар.
  • Разложенные сведения позволяют запрашивать API правильно.
public void ExtractIdentifierDetails()
{
    ContosoUser user = GetFromDb("[email protected]");

    string rawId = user.CommunicationIdentifier;
    CommunicationIdentifier teamsUser = CommunicationIdentifier.FromRawId(rawId);
    switch (communicationIdentifier)
    {
        case MicrosoftTeamsUserIdentifier teamsUser:
            string getPhotoUri = $"https://graph.microsoft.com/v1.0/users/{teamsUser.UserId}/photo/$value";
            // ...
            break;
        case CommunicationIdentifier communicationUser:
            string getPhotoUri = GetAvatarFromDB(communicationUser.Id);
            // ...
            break;
    }
}

Вы можете получить доступ к свойствам или методам для определенного CommunicationIdentifier типа, хранящегося в базе данных Contoso в виде строки (необработанный идентификатор).

Использование необработанных идентификаторов в качестве ключа в платформах пользовательского интерфейса

Можно использовать необработанный ID идентификатора в качестве ключа в компонентах пользовательского интерфейса для отслеживания определённого пользователя и предотвращения ненужных перерисовок и вызовов API. В этом примере мы изменим порядок отображения пользователей в списке. В реальном мире мы могли бы захотеть показать новых пользователей в первую очередь или изменить порядок отображения пользователей на основе некоторых условий (например, поднятой руки). Для упрощения в следующем примере порядок отображения пользователей просто меняется на обратный.

import { getIdentifierRawId } from '@azure/communication-common';

function CommunicationParticipants() {
  const [users, setUsers] = React.useState([{ id: getIdentifierRawId(userA), name: "John" }, { id: getIdentifierRawId(userB), name: "Jane" }]);
  return (
    <div>
      {users.map((user) => (
      // React uses keys as hints while rendering elements. Each list item should have a key that's unique among its siblings. 
      // Raw ID can be utilized as a such key.
        <ListUser item={user} key={user.id} />
      ))}
      <button onClick={() => setUsers(users.slice().reverse())}>Reverse</button>
    </div>
  );
}

const ListUser = React.memo(function ListUser({ user }) {
  console.log(`Render ${user.name}`);
  return <div>{user.name}</div>;
});

Дальнейшие действия

В этой статье описано, как:

  • Правильно определить варианты использования для выбора необработанного идентификатора
  • Преобразование между необработанным идентификатором и различными типами CommunicationIdentifier