Reflection Support

Transpose emits metadata alongside your compiled JavaScript so that runtime type inspection through System.Reflection works in the browser.

How it works

By default Transpose generates metadata for every type declared in the project and for all of its members — not only the public ones. The metadata records base types, nested types, accessibility, constructors, methods (with parameter types), fields, properties, events, and the custom attributes applied to each.

Types marked [External] (a binding to native JavaScript) and anything marked [NonScriptable] are excluded, since they have no Transpose-side runtime identity.

The metadata is registered with the runtime through Transpose.setMetadata and lands either in a separate <fileName>.meta.js next to the bundle — the default — or inline in the bundle itself. The generated index.html loads the metadata file when there is one.

Usage

Standard reflection APIs work:

using System;
using System.Reflection;

public class Person
{
    public string Name { get; set; }
    public void SayHello() { }
}

public class Program
{
    public static void Main()
    {
        Type personType = typeof(Person);

        foreach (var prop in personType.GetProperties())
        {
            Console.WriteLine("Property: " + prop.Name);
        }

        foreach (var method in personType.GetMethods())
        {
            Console.WriteLine("Method: " + method.Name);
        }
    }
}

Activator.CreateInstance, attribute lookup via GetCustomAttributes, and MethodInfo.Invoke are backed by the same metadata.

The [Reflectable] attribute

[Reflectable] overrides the default policy for one type or one member.

[Reflectable(false)]              // no metadata for this type at all
public class InternalHelper
{
    public int Id { get; set; }
}

public class MyClass
{
    public int Id { get; set; }

    [Reflectable(false)]          // excluded from this type's metadata
    public string Secret { get; set; }
}

[Reflectable] with no argument means true, which is only useful to re-include a member of a type you would otherwise have filtered.

There is no assembly-level `[Reflectable]`

[assembly: Reflectable(false)] has no effect — the attribute is only read from the type or member it is applied to. To turn reflection off for the whole project, use reflection.disabled in tps.json.

Configuring metadata generation

Two settings in tps.json control the metadata for the whole project:

tps.json
{
  "reflection": {
    "disabled": false,
    "target": "file"
  }
}
  • disabledtrue emits no metadata at all. Reflection APIs will not find your types, but the bundle gets meaningfully smaller.
  • targetfile (the default) writes a separate <fileName>.meta.js; inline puts the metadata in the main bundle. A separate file lets the browser cache the two independently, and lets you skip loading the metadata entirely in a build that does not need it.
The h5 `reflection.filter` option is not supported

h5 accepted a wildcard filter pattern to select which types got metadata. Transpose does not read it. Use [Reflectable(false)] on the types you want to exclude, or turn metadata off for the whole project.

Size

Metadata is proportional to the number of types and members in the project, and for a large application it is a real share of the bundle. If your code does not use reflection — and note that a serialization library or a UI framework you depend on might — measure the difference with reflection.disabled before deciding.

Because the default policy is all-in, [Reflectable(false)] on the large internal types you never reflect over is the cheapest targeted saving.

© 2026 Curiosity. All rights reserved.