Table of Contents

Builder and Configuration

In order for CysTerra to discover your components, you need to define builder types for them. Builder types must be annotated with the ExportAttribute attribute with one of the following contract types.

A discoverable builder type must derive from its contract type, be concrete (not abstract), and have a public parameterless constructor (either explicit or implicit).

For example:

using Cryville.EEW;
using Cryville.EEW.Report;
using System.ComponentModel.Composition;
using System.Globalization;

[Export(typeof(IBuilder<IGenerator<ReportModel>>))]
public class MyReportGeneratorBuilder : IBuilder<MyReportGenerator> {
	public override string? GetName([NotNull] ref CultureInfo? culture) {
		using var lres = new LocalizedResource("", ref culture);
		var res = lres.RootMessageStringSet;
		return res.GetStringRequired("SourceName");
	}
	public MyReportGenerator Build(ref CultureInfo? culture) {
		return new MyReportGenerator();
	}
}

Builder Configuration

Public browsable settable properties in the builder are recognized as builder configurations configurable by the user. These properties are set by the user before Build is called.

Note that only one component built with the same builder and the same set of builder properties can exist at the same time. If no builder configurations is defined in a builder, only one component built with this builder can exist.

using Cryville.EEW;
using Cryville.EEW.Report;
using System.ComponentModel.Composition;
using System.Globalization;

[Export(typeof(IBuilder<IGenerator<ReportModel>>))]
public class MyReportGeneratorBuilder : IBuilder<MyReportGenerator> {
	// Define a configuration named MyConfig
	public bool MyConfig { get; set; }

	public override string? GetName([NotNull] ref CultureInfo? culture) {
		using var lres = new LocalizedResource("", ref culture);
		var res = lres.RootMessageStringSet;
		return res.GetStringRequired("SourceName");
	}
	public MyReportGenerator Build(ref CultureInfo? culture) {
		// MyConfig has been set by the user here
		return new MyReportGenerator(MyConfig);
	}
}

Component Configuration

Like builders, components can have component configurations, which is defined in the same way as in builders. However, the component has to implement IPropertiesHolder for its properties to be recognized as configurations.

using Cryville.EEW;
using Cryville.EEW.Report;
using System.Globalization;

// Implement IPropertiesHolder to add configurations
public class MyReportGenerator : IGenerator<MyEvent, ReportModel>, IPropertiesHolder {
	// Define a configuration named AdditionalConfig
	public bool AdditionalConfig { get; set; }
	
	public ReportModel Generate(MyEvent e, ref CultureInfo culture) {
		/* ... */
	}
}
Note

Builders actually implement IPropertiesHolder as well because IBuilder derives from it.