Study guide

7.2 Attributes & Reflection

Microsoft Dynamics 365: Finance and Operations Apps Developer Associate MB-500

Track your progress as you read

Finished sections get a check mark.

1 Chapter 1: Cloud & Ecosystem Architecture

1.1 Cloud vs On-Premises Architecture & Deployment Typologies 1.2 Microsoft Ecosystem Integration & Extensibility Boundaries 1.3 Lifecycle Services (LCS) & Implementation Portal

2 Chapter 2: ALM, Environments & Unified Developer Experience

2.1 Package Deployment & Servicing 2.2 Unified Developer Experience (UDE) & Power Platform Admin Center 2.3 Environment Management & Governance

3 Chapter 3: Visual Studio Development & Metadata

3.1 Visual Studio Extension Models & Packages 3.2 Application Explorer & Element Designers 3.3 Database Synchronization & Visual Studio Debugging

4 Chapter 4: Azure DevOps Version Control & CI/CD

4.1 Version Control Architecture: TFVC vs Git in F&O 4.2 Branching, Merging & Conflict Resolution 4.3 CI/CD Build Pipelines & Artifact Generation

5 Chapter 5: UI Elements: Forms, Menus & Labels

5.1 Form Design & Form Patterns 5.2 Menus, Menu Items & Navigation 5.3 Label Files & Localization

6 Chapter 6: Data Model: Tables & Relational Design

6.1 Table Design & Extension 6.2 Views, Queries & Maps 6.3 Data Entity Design & Modeling

7 Chapter 7: Classes, Attributes & AOT Modifiers

7.1 Class Architecture & Access Modifiers 7.2 Attributes & Reflection 7.3 Event Handlers & Pre/Post Method Events

8 Chapter 8: X++ Core Programming & CRUD Operations

8.1 X++ Syntax, Control Flow & Global Functions 8.2 Data Manipulation & CRUD Logic 8.3 Best Practice Rules & Compiler Diagnostics

9 Chapter 9: Advanced OOP, Chain of Command & Extensibility

9.1 OOP Principles & QueryBuilder Class 9.2 Chain of Command (CoC) Implementation 9.3 Extensibility Patterns & Non-Breaking Changes 9.4 Event Handler Classes & Delegate Architecture 9.5 Variable Scoping, Declaration Placement & Object Lifetime

10 Chapter 10: F&O Frameworks & SysTest Unit Testing

10.1 SysOperation Framework Architecture 10.2 Workflow Framework & SysExtensionSerializer 10.3 SysTest Framework & Test Explorer

11 Chapter 11: Reporting Architecture & SSRS Reports

11.1 Reporting Architecture & Datastores 11.2 Report Data Providers & Contracts 11.3 SSRS Report Design, Deployment & Security 11.4 Determining When to Use a Specific Reporting Tool or Platform

12 Chapter 12: Business Intelligence, Workspaces & Electronic Reporting

12.1 Electronic Reporting (ER) Framework 12.2 Power BI Integration & Analytical Workspaces 12.3 Workspaces, Tiles, Lists & KPIs 12.4 Excel Integration & Office App

13 Chapter 13: Integration Patterns & Service Endpoints

13.1 Integration Pattern Evaluation & API Selection 13.2 Custom Services & SOAP/REST Endpoints 13.3 Consuming External Services & REST/SOAP APIs

14 Chapter 14: Data Management Framework (DMF) & Batch Processing

14.1 DMF Concepts, Projects & Sequencing 14.2 Entity Change Tracking & Recurring Integrations 14.3 Composite Entities & Batch OData API 14.4 Monitoring Entity Status, Availability & Job Execution

15 Chapter 15: Power Platform, Business Events & Azure Integrations

15.1 Dual-Write & Virtual Entities 15.2 Business Events Framework 15.3 Azure Key Vault Integration & Secure Storage

16 Chapter 16: Role-Based Security & Extensible Data Security

16.1 Role-Based Security Architecture 16.2 Extensible Data Security (XDS) Policies 16.3 Security Enforcement & Best Practices

17 Chapter 17: Performance Optimization & Data Access Patterns

17.1 Table & Form Caching Mechanisms 17.2 Temporary Tables & Set-Based Operations 17.3 Query Tuning, Indexes & Concurrency 17.4 Diagnostics: Trace Parser, Async & Sandbox Frameworks 17.5 Tuning Variable Scope, Buffer Lifetime & Memory Pressure

7.2 Attributes & Reflection

Key Takeaways Explain This Topic AI

Attributes in X++ are declarative classes derived from SysAttribute that annotate classes, methods, and tables with metadata evaluated at compile-time and runtime.

The SysOperation framework relies on [DataContractAttribute] to mark parameter storage classes and [DataMemberAttribute] to expose serialized accessor methods across asynchronous and batch tiers.

Custom and standard service operations exposed via SOAP or JSON REST endpoints must be decorated with [SysEntryPointAttribute(true)] to enforce role-based security privilege checks prior to execution.

Extensibility controls include [Hookable(false)] to block pre/post method events and Chain of Command wrapping, [ExtensionOf] to bind augmentation classes, and [SysObsoleteAttribute] to signal API deprecation.

Reflection in modern X++ utilizes Dictionary reflection classes—primarily DictClass, DictMethod, and SysDictType—to discover attributes at runtime and dynamically invoke methods via callObject().

Last updated: September 2026

7.2 Attributes & Reflection

Quick Answer: Attributes in X++ are metadata classes inheriting from SysAttribute that annotate classes, methods, and tables. In the SysOperation framework, [DataContractAttribute] designates parameter serialization containers, while [DataMemberAttribute('Name')] marks getter/setter parameter methods. External services mandate [SysEntryPointAttribute(true)] to trigger Application Object Server (AOS) role-based authorization. Extensibility boundaries are governed by [Hookable(false)] (which prohibits both pre/post events and Chain of Command wrapping), [ExtensionOf] (which binds CoC augmentation classes), and [SysObsoleteAttribute] (which flags deprecated APIs with warnings or errors). Reflection APIs—principally DictClass , DictMethod , and SysDictType —inspect metadata dynamically at runtime, query attributes via isAttributeDefined() and getAttribute() , and invoke dynamic methods via DictClass.callObject() .

1. Attribute-Driven Architecture in X++

Attributes provide a structured mechanism for attaching declarative metadata to X++ code elements without altering their core operational logic. When code is compiled, attribute declarations are emitted directly into the assembly metadata of the generated .NET assemblies.

The Core Attribute Lifecycle

Design Time: Developers declare attributes on classes, tables, forms, or methods.

Compile Time: The X++ compiler validates attribute targets, serializes attribute constructor arguments into assembly metadata, and enforces compiler constraints (e.g., verifying [ExtensionOf] syntax).

Runtime: Framework engines (such as the SysOperation framework, FormRun engine, or integration services) use reflection to discover attributes and alter processing pipelines.

2. Designing Custom Attributes with SysAttribute

To create a custom attribute in X++, a developer declares a class that directly extends the system base class SysAttribute .

Implementation Rules for Custom Attributes

Must inherit from SysAttribute .

Typically ends with the suffix Attribute (e.g., PaymentIntegrationAttribute ).

Can declare instance variables and a constructor to receive declarative arguments.

Stored state should be exposed through public getter methods. /// <summary>

/// Custom attribute marking integration handler classes with protocol metadata.

  • /// </summary>
  • public final class ExportFormatAttribute extends SysAttribute
  • {
  • private str formatName;
  • private boolean supportsCompression;
  • public void new(str _formatName, boolean _supportsCompression = false)
  • {
  • super();
  • this.formatName = _formatName;
  • this.supportsCompression = _supportsCompression;
  • }
  • public str parmFormatName()
  • {
  • return formatName;
  • }
  • public boolean parmSupportsCompression()
  • {
  • return supportsCompression;
  • }
  • }
  • Decorating Target Classes

Once compiled, the custom attribute can annotate any class or method: [ExportFormatAttribute("ISO20022_XML", true)]

  • public class ISO20022PaymentExporter extends PaymentExporterBase
  • {
  • // Format-specific export implementation
  • }
  • 3. Key Platform Attributes: Deep Architectural Breakdown

Dynamics 365 Finance and Operations relies heavily on standardized platform attributes to govern serialization, security, extensibility, and lifecycle management.

Comprehensive Platform Attribute Matrix

Attribute Name Target Elements Primary Functional Purpose Runtime / Compiler Behavior

[DataContractAttribute] Class Defines a serialization contract for SysOperation or integration services. Enables CLR XML/JSON serialization between tiers and batch storage.

[DataMemberAttribute] Method Exposes a parameter getter/setter method inside a Data Contract. Serializes individual member values; accepts optional alias string.

[SysEntryPointAttribute] Method Enforces role-based security authorization on service operations. When true , verifies calling user permissions; when false , bypasses checks.

[Hookable(false)] Method / Class Completely closes an element to external extensibility hooks. Blocks both Pre/Post event subscriptions and Chain of Command wrapping.

[ExtensionOf] Class Designates an augmentation class for Chain of Command (CoC). Compiler links class to target element; requires final class ..._Extension .

[SysObsoleteAttribute] Class / Method Marks obsolete code and guides developers to replacement APIs. Generates compiler warnings (if isError = false ) or errors (if true ).

[ExportMetadataAttribute] Class Attaches key-value metadata to MEF (Managed Extensibility Framework) plugins. Used by kernel plugin engines for zero-compilation pluggable extensions.

Deep Dive: [DataContractAttribute] and [DataMemberAttribute]

In the SysOperation framework, parameters cannot be passed as raw table buffers or loose primitives across tier boundaries. Instead, parameters are encapsulated inside a Data Contract class decorated with [DataContractAttribute] .

Each member property is exposed via a public parm method decorated with [DataMemberAttribute('Name')] .

The runtime serializes the contract into an XML pack string stored in SysOperationDataContractInfo inside the batch tables ( BatchJob , Batch ). [DataContractAttribute]

  • public class CustInvoiceBatchContract
  • {
  • private CustAccount customerAccount;
  • private TransDate fromDate;
  • [DataMemberAttribute('CustAccount')]
  • public CustAccount parmCustAccount(CustAccount _customerAccount = customerAccount)
  • {
  • customerAccount = _customerAccount;
  • return customerAccount;
  • }
  • [DataMemberAttribute('FromDate')]
  • public TransDate parmFromDate(TransDate _fromDate = fromDate)
  • {
  • fromDate = _fromDate;
  • return fromDate;
  • }
  • }
  • Deep Dive: [SysEntryPointAttribute(true)]

When exposing a custom service in Dynamics 365 (SOAP or JSON REST), the service operation method must be decorated with [SysEntryPointAttribute] :

[SysEntryPointAttribute(true)] : The Application Object Server (AOS) inspects the user's security privileges before allowing execution. If the user lacks access to the entry point menu item or service privilege, an AccessDeniedException is thrown.

[SysEntryPointAttribute(false)] : Disables automated authorization checks. Execution proceeds without entry-point security validation. This should be used strictly for internal diagnostics or anonymous utility endpoints.

Deep Dive: [Hookable(true/false)]

By default, all public and protected methods in X++ are hookable.

[Hookable(false)] : Explicitly prevents developers from creating Pre/Post event handlers and prevents wrapping the method via Chain of Command (CoC).

Why Microsoft uses [Hookable(false)] : Applied to critical transactional or kernel algorithms (such as core ledger posting loops or cryptographic hashing) where external interference could corrupt transactional consistency or bypass security.

Deep Dive: [SysObsoleteAttribute]

When refactoring or deprecating APIs, developers use [SysObsoleteAttribute(str _message, boolean _isError)] :

_message : Explanation of the deprecation and reference to the replacement API.

_isError = false : Generates a compiler warning during build.

_isError = true : Generates a fatal compilation error, breaking any build that attempts to call the obsolete method.

4. Reflection APIs in X++: DictClass , DictMethod & SysDictType

Reflection enables X++ programs to inspect application metadata dynamically at runtime without knowing type definitions at compile time. Dynamics 365 provides dedicated Dictionary classes.

Core Reflection Classes

DictClass : Inspects class metadata. Allows querying superclasses, implemented interfaces, declared methods, custom attributes, and provides dynamic object instantiation and method execution.

DictMethod : Inspects method metadata. Retrieves parameter counts, parameter types, return types, and method visibility.

SysDictType : Inspects Extended Data Types (EDTs) and primitive types. Retrieves string length, decimal precision, labels, and underlying base types.

DictTable : Inspects table metadata, fields, indexes, and relations.

5. Dynamic Method Invocation and Attribute Querying

Reflection is widely used in extensible enterprise frameworks to dynamically discover and invoke classes based on configuration records.

Inspecting Attributes at Runtime public static boolean hasExportFormatAttribute(ClassName _className, str _expectedFormat)

  • {
  • ClassId classId = className2Id(_className);
  • if (!classId)
  • {
  • return false;
  • }

DictClass dictClass = new DictClass(classId);

  • // Check if the custom attribute is defined on the class
  • if (dictClass.isAttributeDefined(classStr(ExportFormatAttribute)))
  • {
  • // Retrieve the instantiated attribute object
  • ExportFormatAttribute attr = dictClass.getAttribute(classStr(ExportFormatAttribute)) as ExportFormatAttribute;
  • if (attr && attr.parmFormatName() == _expectedFormat)
  • {
  • return true;
  • }
  • }
  • return false;
  • }

Dynamic Instantiation and Invocation via DictClass public static str executeDynamicProcessor(ClassName _className, str _payload)

  • {
  • ClassId classId = className2Id(_className);
  • DictClass dictClass = new DictClass(classId);
  • if (!dictClass)
  • {
  • throw error(strFmt("Class %1 does not exist.", _className));
  • }
  • // Dynamically instantiate the object via makeObject
  • Object processorInstance = dictClass.makeObject();
  • // Verify method existence
  • if (dictClass.findObjectMethodObject(methodStr(PaymentExporterBase, processPayload)))
  • {
  • // Dynamically invoke method passing parameters via container
  • return dictClass.callObject(methodStr(PaymentExporterBase, processPayload), processorInstance, _payload);
  • }
  • throw error("Method not implemented on target class.");
  • }
  • 6. Scenario Walk-Through: Dynamic Plugin Discovery Framework
  • Scenario Description

An enterprise shipping portal must dynamically discover and execute carrier tracking plugins (FedEx, UPS, DHL). New carrier plugins must be deployable by ISVs without altering the core shipping engine codebase. The system must query all classes decorated with [CarrierPluginAttribute] , find the matching carrier ID, instantiate the class dynamically, and invoke its tracking endpoint.

Implementation Walk-Through

Declare the Custom Attribute ( CarrierPluginAttribute ):

Extend SysAttribute with parameter CarrierCode carrierCode .

Annotate Concrete Carrier Plugins:

Decorate FedExCarrierService with [CarrierPluginAttribute("FEDEX")] .

Decorate UPSCarrierService with [CarrierPluginAttribute("UPS")] .

Scan Metadata via SysExtensionAppClassCache / DictClass :

Query candidate classes implementing interface ICarrierService .

For each class, inspect dictClass.getAttribute(classStr(CarrierPluginAttribute)) .

Match and Execute:

When the user tracks a FedEx parcel, match "FEDEX" .

Instantiate via dictClass.makeObject() and cast to ICarrierService .

Invoke carrierService.trackShipment(trackingNum) .

7. Real-World Exam Traps: Attributes & Reflection

Warning

Exam Trap 1: Setting [SysEntryPointAttribute(false)] on Production Custom Services An exam scenario describes a custom REST service that external users can execute even without having assigned security privileges. The cause is that the service operation was decorated with [SysEntryPointAttribute(false)] . Setting this property to false disables automated authorization. The correct production configuration is [SysEntryPointAttribute(true)] .

Warning

Exam Trap 2: Omitting [DataMemberAttribute] on Contract Methods A developer creates a Data Contract class with [DataContractAttribute] , but when the batch job executes, parameter values reset to blank or null. The developer forgot to decorate the parm getter/setter methods with [DataMemberAttribute] . Without [DataMemberAttribute] , the serialization engine ignores the property entirely.

Warning

Exam Trap 3: Believing [Hookable(false)] Only Blocks Pre/Post Events An exam question asks how to prevent external developers from wrapping a method using Chain of Command (CoC) when the method cannot be marked final . The correct solution is decorating the method with [Hookable(false)] . [Hookable(false)] blocks both Pre/Post event subscriptions and Chain of Command wrapping.

Warning

Exam Trap 4: Passing Incorrect Argument Types to DictClass.callObject() When calling DictClass.callObject() , arguments passed must match the method signature exactly. If arguments are passed incorrectly or the method is static instead of an instance method ( callStatic must be used for static methods), a fatal CLR reflection exception is thrown.

Loading diagram... Attribute Processing Lifecycle and Reflection Inspection Pipeline