Skip to main content

Overview

ComponentBinding represents a mapping between server-side types and client-side UI components. It implements the IComponentBinding interface and is used by the metadata binder to determine which component should be used to render a specific type.

Namespace

UiMetadataFramework.Core.Binding

Interfaces

  • IComponentBinding

Properties

Category
string
Component category to which this component belongs. Components within the same category must have unique names. Common categories include "input" and "output" (see MetadataBinder.ComponentCategories).
ComponentType
string
Name of the client-side component that will be rendered. This corresponds to the component name on the client.
ServerTypes
IEnumerable<Type>
Collection of server-side types that are mapped to this component. Multiple types can be bound to the same component.
MetadataFactory
Type?
Type of the IMetadataFactory to use for constructing component metadata. If null, DefaultMetadataFactory will be used.
AllowedConfigurations
HasConfigurationAttribute[]
Array of allowed configurations for this component. Configurations customize component behavior and appearance.
AdditionalData
IReadOnlyDictionary<string, object?>?
Additional data associated with this component type. Can be used to pass custom metadata to the client.

Constructors

Single Server Type Constructor

public ComponentBinding(
    string category,
    Type serverType,
    string componentType,
    Type? metadataFactory,
    params HasConfigurationAttribute[] allowedConfigurations)
Creates a binding for a single server type.
category
string
Component category (e.g., “input” or “output”).
serverType
Type
Server-side type to bind to the component.
componentType
string
Name of the client-side component.
metadataFactory
Type?
Metadata factory type, or null to use the default.
allowedConfigurations
HasConfigurationAttribute[]
Allowed configurations for the component.

Multiple Server Types Constructor

public ComponentBinding(
    string category,
    IEnumerable<Type> serverTypes,
    ComponentAttribute attribute,
    params HasConfigurationAttribute[] allowedConfigurations)
Creates a binding for multiple server types using a component attribute.
category
string
Component category.
serverTypes
IEnumerable<Type>
Collection of server-side types to bind to the component.
attribute
ComponentAttribute
Component attribute containing component configuration.
allowedConfigurations
HasConfigurationAttribute[]
Allowed configurations for the component.

Methods

GetAdditionalData<T>

public T? GetAdditionalData<T>(string key)
Attempts to retrieve a value from AdditionalData with the specified key and of the specified type.
key
string
Key of the item in AdditionalData.
T
Type
Type that the value should have. If the value exists but is not of this type, the default value will be returned.
Returns: Value from AdditionalData or default if no matching value was found.

Equals

public override bool Equals(object? obj)
Determines whether two component bindings are equal based on their category, component type, and server types.

GetHashCode

public override int GetHashCode()
Returns a hash code for the component binding.

Usage Examples

Creating a Simple Component Binding

var binding = new ComponentBinding(
    category: MetadataBinder.ComponentCategories.Input,
    serverType: typeof(string),
    componentType: "text",
    metadataFactory: null
);

Creating a Binding with Multiple Server Types

var binding = new ComponentBinding(
    category: MetadataBinder.ComponentCategories.Input,
    serverTypes: new[] { typeof(int), typeof(long), typeof(decimal) },
    componentType: "number",
    metadataFactory: typeof(NumberMetadataFactory)
);

Creating a Binding with Configurations

public class MaxLengthConfiguration : HasConfigurationAttribute
{
    public int MaxLength { get; set; }
}

public class MinLengthConfiguration : HasConfigurationAttribute
{
    public int MinLength { get; set; }
}

var binding = new ComponentBinding(
    category: MetadataBinder.ComponentCategories.Input,
    serverType: typeof(string),
    componentType: "text",
    metadataFactory: null,
    allowedConfigurations: new HasConfigurationAttribute[]
    {
        new MaxLengthConfiguration(),
        new MinLengthConfiguration()
    }
);

Using Component Binding with MetadataBinder

public class CustomComponentBinding : ComponentBinding
{
    public CustomComponentBinding()
        : base(
            category: MetadataBinder.ComponentCategories.Input,
            serverType: typeof(CustomType),
            componentType: "custom-input",
            metadataFactory: typeof(CustomMetadataFactory))
    {
    }
}

// Register the binding
var binder = new MetadataBinder();
binder.RegisterAssembly(typeof(CustomComponentBinding).Assembly);

Accessing Additional Data

public class RichComponentBinding : ComponentBinding
{
    public RichComponentBinding()
        : base(
            category: MetadataBinder.ComponentCategories.Output,
            serverTypes: new[] { typeof(RichContent) },
            attribute: new ComponentAttribute("rich-editor")
            {
                // Additional data can be set via the attribute
            })
    {
        // Set additional data
        AdditionalData = new Dictionary<string, object?>
        {
            ["syntax-highlighting"] = true,
            ["theme"] = "dark",
            ["plugins"] = new[] { "spellcheck", "wordcount" }
        };
    }
}

// Later, retrieve the data
var syntaxHighlighting = binding.GetAdditionalData<bool>("syntax-highlighting");
var theme = binding.GetAdditionalData<string>("theme");
var plugins = binding.GetAdditionalData<string[]>("plugins");

Custom Component Binding Class

public class DateRangeInputBinding : ComponentBinding
{
    public DateRangeInputBinding()
        : base(
            category: MetadataBinder.ComponentCategories.Input,
            serverType: typeof(DateRange),
            componentType: "date-range",
            metadataFactory: typeof(DateRangeMetadataFactory),
            allowedConfigurations: new HasConfigurationAttribute[]
            {
                new MinDateConfiguration(),
                new MaxDateConfiguration()
            })
    {
    }
}

public class DateRange
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}

IComponentBinding Interface

The IComponentBinding interface defines the contract that all component bindings must implement:
public interface IComponentBinding
{
    IReadOnlyDictionary<string, object?>? AdditionalData { get; }
    HasConfigurationAttribute[] AllowedConfigurations { get; }
    string ComponentType { get; }
    Type? MetadataFactory { get; }
    IEnumerable<Type> ServerTypes { get; }
}

Notes

  • Component bindings are typically created by inheriting from ComponentBinding and registering them with the MetadataBinder.
  • Multiple server types can be mapped to the same component, allowing for type consolidation on the client side.
  • The MetadataFactory property allows for custom metadata generation logic.
  • Additional data can be used to pass component-specific configuration to the client.
  • Component bindings are automatically discovered and registered when calling MetadataBinder.RegisterAssembly().

See Also

Build docs developers (and LLMs) love