To create a Custom Entity you need a interface and a implementation of it. This is the example interface for a custom entity, all custom entities need to inherit from IBaseEntity.
using LemonEdge.API.Attributes;
using LemonEdge.API.Entities;
using LemonEdge.Examples.CustomEntity.Core.Entities;
using LemonEdge.Utils;
using LemonEdge.Utils.Database;
namespace LemonEdge.Examples.CustomEntity.Core.Interfaces;
/// <summary>
/// Our entity implements <see cref="IBaseEntity" />
/// We use the <see cref="DefaultEntityIconAttribute" /> to set the image of the entity in the UI
/// We use the <see cref="EntityDescriptionAttribute" /> to set the description of the entity
/// We use the <see cref="EntityDefinitionAttribute" /> to set various properties of the entity such as its unique ID,
/// its table name, its singular item name
/// (a SetName property may be supplied or will be generated by pluralizing the ItemName).
/// The LabelColumn is what will be used when this item is displayed as a link or relationship to another entity
/// </summary>
[DefaultEntityIcon(ImageType.Property)]
[EntityDescription("Represents a Custom Entity")]
[EntityDefinition(EntityHelper.CustomEntityIDString, "dbo.CE_CustomEntity", "CustomEntity",
LabelColumn = nameof(SomeCustomString))]
public interface ICustomEntity : IBaseEntity
{
/// <summary>
/// The <see cref="EntityPropertyAttribute" /> allows us to define SQL specific attributes of each specific property
/// such as its type, length, or nullability.
/// </summary>
[EntityProperty(SQLType.BigInt, true)]
[EntityDescription("Some Custom Number")]
long? SomeCustomNumber { get; set; }
[EntityProperty(SQLType.NVarChar, 200, false)]
[EntityDescription("Some Custom String")]
string SomeCustomString { get; set; }
[EntityProperty(SQLType.Bit, false)]
[EntityDescription("Some Custom Boolean")]
bool SomeCustomBool { get; set; }
}
This is the concrete implementation of the ICustomEntity.
These are the requared references for this example.
using System.Runtime.Serialization;
using LemonEdge.API.Entities;
using LemonEdge.Examples.CustomEntity.Core.Interfaces;
using LemonEdge.Utils.Interfaces;
The constructor needs to inherit from BaseEntity, the created custom entity interface ICustomEntity, and ICloneableAsync
[DataContract]
public class CustomEntity : BaseEntity, ICustomEntity, ICloneableAsync<ICustomEntity>
These can be auto generated using LemonEdge's AutoCodeGenerator for cumbersome entities.
[DataMember] private bool _someCustomBool;
[DataMember] private long? _someCustomNumber;
[DataMember] private string _someCustomString;
public long? SomeCustomNumber
{
get => _someCustomNumber;
set
{
if (_someCustomNumber != value)
{
OnPropertyChanging(nameof(SomeCustomNumber));
_someCustomNumber = value;
OnPropertyChanged(nameof(SomeCustomNumber));
}
}
}
public string SomeCustomString
{
get => _someCustomString;
set
{
if (_someCustomString != value)
{
OnPropertyChanging(nameof(SomeCustomString));
_someCustomString = value;
OnPropertyChanged(nameof(SomeCustomString));
}
}
}
public bool SomeCustomBool
{
get => _someCustomBool;
set
{
if (_someCustomBool != value)
{
OnPropertyChanging(nameof(SomeCustomBool));
_someCustomBool = value;
OnPropertyChanged(nameof(SomeCustomBool));
}
}
}
Implementation of ICloneableAsync methods.
public void CopyFromSource(ICustomEntity source)
{
CopyFromEntity(source);
}
async Task<ICustomEntity> ICloneableAsync<ICustomEntity>.Clone(object context)
{
return (ICustomEntity)await Clone(context);
}
protected override void CopyFromEntity(IBaseEntity src)
{
base.CopyFromEntity(src);
var source = (ICustomEntity)src;
_someCustomBool = source.SomeCustomBool;
_someCustomString = source.SomeCustomString;
_someCustomNumber = source.SomeCustomNumber;
}
The EntityHelper will track specific data about our add-in. All entities (commands are an entity as well) will need a unique ID.
public class EntityHelper
{
// This will be the ID of the custom entity itself. You may generate this GUID using an GUID generator.
public const string CustomEntityIDString = "A589E2CF-F97B-4FCD-9C0D-108EF5CEABFF";
// This is the command (i.e. button on the UI). Here we can use the CommandAttribute to set the title text, the button image, the hover tooltip, etc.
[Command("Custom Entity", ImageType.Binoculars, "Explore Custom Entities", ImageType.None,
"Explore Custom Entities")]
public const string CustomEntityCommandIDString = "7E48FEFE-7047-4A3D-87FA-E7758B9F6211";
public static Guid CustomEntityCommandID => Guid.Parse(CustomEntityCommandIDString);
}
The IDefaultMenuInserter will create and display a menu item with the supplied details per use role(i.e. admin, standard, etc.)
public class MenuInserter : IDefaultMenuInserter
{
public async Task UpdateDefaultMenus(IDefaultMenuItemCreator menuCreator)
{
// The TabIndex determines which tab this menu item will appear on (i.e. API, Financial Services, Settings, etc.)
short tabIndex = 6;
// The GroupIndex determines where the menu item will be grouped within a tab
short groupIndex = 1;
// The ItemIndex determines where the menu item will be displayed within a group
short itemIndex = 1;
// The specific name of the tab
var tabName = "Custom Tab";
// The specific name of the group
var groupName = "Custom Tab";
// The menu item name will come from the Command Attribute on EntityHelper.CustomEntityCommandID
var customEntityButton =
CommandAttribute.GetDescriptors(typeof(EntityHelper), EntityHelper.CustomEntityCommandID);
await menuCreator.CreateMenuItem(
// The role to which this menu item is assigned
menuCreator.AdminRoleID,
tabIndex,
tabName,
// If this menu item should be shown on all menus/tabs (similar to the save menu item)
false,
groupIndex,
groupName,
itemIndex,
customEntityButton,
// If this command should be activated when the system loads rather than by some CanExecute boolean
false,
// If this command should be added near the user menu (top-right)
false,
// If this command should be added within the user menu
false,
// If this command should be added to the quick-access menu
false,
// Whether this command is visible or not
true,
// Whether this command should still be visible when the simplified toggle is true
false);
await menuCreator.CreateMenuItem(menuCreator.StandardRoleID, tabIndex, tabName, false, groupIndex, groupName,
itemIndex, customEntityButton, false, false, false, false, true, false);
}
}