Home » Пользовательская модель сущности Optimizely Commerce Business Foundation — для добавления в блог Quan Mai :)

Пользовательская модель сущности Optimizely Commerce Business Foundation — для добавления в блог Quan Mai :)

Куан Май прав.есть еще один официальный способ загрузки организаций и контактов в Optimizely Commerce с использованием известного статического класса BusinessManager. Тем не менее, вы можете сделать больше. Вы когда-нибудь задумывались, можете ли вы персонализировать доступ к данным в пользовательских свойствах, используя свой собственный класс вместо использования, например, Organization.Properties["MyCustomProperty"]? Да, я тоже, и в этом блоге я покажу вам, что это возможный!

Для простоты чтения я сосредоточу обсуждение на организациях, но имейте в виду, что тот же принцип персонализации применяется ко всем другим объектам Business Foundation. Наше путешествие начнется с файла конфигурации; baf.data.manager.config. В этом файле перечислены несколько сущностей Business Foundation со связанными с ними RequestHandler. Вы видите здесь конфигурацию по умолчанию для Organization является следующим типом: Mediachase.Commerce.Customers.Handlers.OrganizationRequestHandler, Mediachase.Commerce. Если у вас есть Jetbains Rider, вы можете легко найти класс, выполняя поиск везде, обычно CTRL + T с привязкой клавиш Visual Studio и включая элементы, не являющиеся решением. Для тех, кто использует dotPeek на примере, необходимо декомпилировать dll Mediachase.Commerce.dll который находится в пакете NuGet EPiServer.Commerce.Core.

OrganizationRequestHandler наследует CustomerRequestHandlerBase и здесь мы найдем то, что ищем. Есть метод CreateEntityObjectкоторый имеет следующую строку:

return new CustomerEntityFactory().Create((object) new KeyValuePair(metaClassName, primaryKeyId));

Если присмотреться, внутри класса CustomerEntityFactory, вы можете узнать, как Business Foundation создает свои экземпляры классов, которые будут возвращены вам после извлечения данных. Вот почему вы можете использовать «OfType» при использовании BusinessManager. Класс довольно простой, для любой известной сущности используйте следующий новый экземпляр класса для создания моей сущности:

EntityObject IFactoryMethod.Create(object obj)
    {
      KeyValuePair keyValuePair = obj != null ? (KeyValuePair) obj : throw new ArgumentNullException(nameof (obj));
      EntityObject entityObject = (EntityObject) null;
      switch (keyValuePair.Key)
      {
        case "Contact":
          entityObject = (EntityObject) CustomerContact.CreateInstance();
          break;
        case "Address":
          entityObject = (EntityObject) CustomerAddress.CreateInstance();
          break;
        case "Organization":
          entityObject = (EntityObject) Organization.CreateInstance();
          break;
        case "CreditCard":
          entityObject = (EntityObject) CreditCard.CreateInstance();
          break;
      }
      if (entityObject != null && keyValuePair.Value.HasValue)
        entityObject.PrimaryKeyId = new PrimaryKeyId?(keyValuePair.Value.Value);
      return entityObject;
    }

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

  1. Создайте свою собственную сущность.
  2. Создайте новую фабрику сущностей.
  3. Создайте новый обработчик запросов.

1. Создайте свою собственную сущность

Мы персонализируем наши Organization сущность с дополнительными свойствами, мы хотим, чтобы они были доступны без вызова Properties["MyProperty"]. Итак, здесь мы создадим новую модель, скажем, MyOrganization, которая будет наследоваться от Mediachase.Commerce.Customers.Organization:

using System;
using System.Collections.Generic;
using Mediachase.BusinessFoundation.Data;
using Mediachase.Commerce.Customers;
using Mediachase.Commerce.Customers.Request;

namespace MyNamespace
{
    public class MyOrganization : Organization
    {
        public string MyInternalOrgNumber
        {
            get => (string) this[nameof(MyInternalOrgNumber)];
            set => this[nameof(MyInternalOrgNumber)] = value;
        }
    }
}

В предыдущем примере я хочу, чтобы разработчики могли получить доступ к нашему пользовательскому свойству «MyInternalOrgNumber» из этого объекта. Это в основном то же самое, что и вызов Organization.Properties["MyInternalOrgNumber"]. Не забывайте, что теперь, чтобы использовать свой собственный класс, вам нужно привести его к «MyOrganization». Вы можете сделать это на прикладном уровне, отвечающем за получение данных из BusinessManager. Что мы сделали в нашем проекте, так это создали сервис, который был абстракцией уровня данных между нашим приложением и Business Foundation. Любые звонки на CustomerContextнапример, CustomerContext.Current.GetOrganizations() можно также перевести в “MyOrganization” (насколько я помню™️).

2. Создайте фабрику сущностей

У тебя еще есть класс CustomerEntityFactory декомпилировано? Вернитесь туда и скопируйте его, потому что в вашей реализации он будет почти таким же:

using System;
using System.Collections.Generic;
using MyEntityModelsNamespace;
using Mediachase.BusinessFoundation.Common;
using Mediachase.BusinessFoundation.Data;
using Mediachase.BusinessFoundation.Data.Business;
using Mediachase.Commerce.Customers;

namespace MyNamespace
{
    public class MyEntityFactory : AbstractFactory, IFactoryMethod
    {
        /// Creates the specified obj.
        /// The obj.
        /// 
        EntityObject IFactoryMethod.Create(object obj)
        {
            var keyValuePair = (KeyValuePair?) obj ?? throw new ArgumentNullException(nameof(obj));
            var key = keyValuePair.Key;
            EntityObject entityObject = key switch
            {
                ContactEntity.ClassName => CustomerContact.CreateInstance(),
                AddressEntity.ClassName => CustomerAddress.CreateInstance(),
                OrganizationEntity.ClassName => new MyOrganization(),
                CreditCardEntity.ClassName => CreditCard.CreateInstance()
                _ => default
            };

            if (entityObject != null && keyValuePair.Value.HasValue)
                entityObject.PrimaryKeyId = keyValuePair.Value.Value;

            return entityObject;
        }
    }
}

3. Создайте обработчик запросов

Для организации, как я уже упоминал ранее, по умолчанию используется Mediachase.Commerce.Customers.Handlers.OrganizationRequestHandler, Mediachase.Commerce как тип. Тогда наш класс будет выглядеть так:

using System.Collections.Generic;
using Mediachase.BusinessFoundation.Data;
using Mediachase.BusinessFoundation.Data.Business;
using Mediachase.Commerce.Customers.Handlers;

namespace MyNamespace
{
    public class MyOrganizationRequestHandler : OrganizationRequestHandler
    {
        protected override EntityObject CreateEntityObject(string metaClassName, PrimaryKeyId? primaryKeyId)
        {
            return new MyEntityFactory().Create(new KeyValuePair(metaClassName, primaryKeyId));
        }
    }
}

Последний штрих; Измените конфигурацию в файле baf.data.manager.config чтобы указать его на ваш новый обработчик запросов. В нашем примере файл должен иметь следующую строку вместо строки по умолчанию для организации:


Последние мысли

Может быть, это может быть немного излишним делать это только для того, чтобы иметь возможность использовать свой собственный класс для сущностей, но, в конце концов, это очень помогло. Искать ссылку проще; мы можем легко найти, кто использует определенное пользовательское свойство и еще много чего. Кроме того, это немного улучшает читаемость. Еще одно потенциальное преимущество этого подхода заключается в том, что новые разработчики, особенно младшие, обычно не привыкли к определенному уровню сложности, который влечет за собой Business Foundation.

Read more:  Площадь поверхности и глубина дизайна продукта

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.