Куан Май прав.есть еще один официальный способ загрузки организаций и контактов в 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. Создайте свою собственную сущность
Мы персонализируем наши 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.