IAsset
Asset is a class that manages localization sources. Sources are typically files, embedded resources, and plain code.
// Language string source
Dictionary<string, string> src = new Dictionary<string, string> { { "en:hello", "Hello World!" } };
// Create Asset
IAsset asset = new StringAsset(src, LineParameterPrinter.Default);
IAsset is the root interface for assets. It serves as a signal that the implementing class has further asset features. There are more specific interfaces such as IStringAsset and IBinaryAsset which retrieve language strings and binary resources.
Asset interfaces are not called directly but used instead by calling extension methods of IAsset.
// Create key
ILine key = new LineRoot().Key("hello").Culture("en");
// Resolve string - Call to StringAssetExtensions.GetString()
IString str = asset.GetLine(key).GetString();
Asset Composition
AssetComposition is the default class. It unifies a group of assets into one asset, typically so that they can be assigned to ILineRoot.
// Create individual assets
IAsset asset_1 = new StringAsset(new Dictionary<string, string> { { "Culture:en:Key:hello", "Hello World!" } }, LineFormat.Parameters);
IAsset asset_2 = new ResourceStringDictionary(new Dictionary<string, byte[]> { { "Culture:en:Key:Hello.Icon", new byte[] { 1, 2, 3 } } }, LineFormat.Parameters);
// Create composition asset
IAssetComposition asset_composition = new AssetComposition(asset_1, asset_2);
// Assign the composition to root
ILineRoot root = new LineRoot(asset_composition, new CulturePolicy());
IAssetComposition is the interface for classes that composes IAsset components.
/// <summary>
/// Composition of <see cref="IAsset"/> components.
/// </summary>
public interface IAssetComposition : IAsset, IList<IAsset>
{
/// <summary>
/// Set to new content.
/// </summary>
/// <param name="newContent"></param>
/// <exception cref="InvalidOperationException">If compostion is readonly</exception>
void CopyFrom(IEnumerable<IAsset> newContent);
/// <summary>
/// Get component assets that implement T.
/// </summary>
/// <param name="recursive">if true, visits children recursively</param>
/// <typeparam name="T"></typeparam>
/// <returns>enumerable or null</returns>
IEnumerable<T> GetComponents<T>(bool recursive) where T : IAsset;
}
Asset Builder
AssetBuilder is a factory class that constructs new instances of IAsset. Asset builder is populated with IAssetSources which participate to the build process.
This example shows how to create asset builder, add asset sources, and then to build an asset.
// Create dictionary of strings
Dictionary<string, string> strings = new Dictionary<string, string> { { "en:hello", "Hello World!" } };
// Create IAssetSource that adds cache
IAssetSource assetSource_0 = new AssetCacheSource(c => c.AddResourceCache().AddStringsCache().AddCulturesCache());
// Create IAssetSource that static reference of IAsset (string dictionary)
IAssetSource assetSource_1 = new AssetFactory(new StringAsset(strings, LineParameterPrinter.Default) );
// Create AssetBuilder
IAssetBuilder builder = new AssetBuilder(assetSource_0, assetSource_1);
// Instantiate IAsset
IAsset asset = builder.Build();
// Create string key
ILine key = new LineRoot().Key("hello").Culture("en");
// Request value
IString value = asset.GetLine( key ).GetString();
// Print result
Console.WriteLine(value);
There are extension methods for convenience.
// Create AssetBuilder
IAssetBuilder builder = new AssetBuilder();
// Add IAssetSource that adds cache
builder.AddCache();
// Add IAssetSource that adds strings
builder.AddStrings(strings, LineParameterPrinter.Default);
Asset builders and asset sources are used with Dependency Injection. Asset sources are added to IServiceCollection to participate in constructing in new assets. Asset builder makes the new asset when requested by ServiceProvider. The calling assembly must have nuget dependency to Microsoft.Extensions.DependencyInjection.Abstractions.
// Initialize service collection
IServiceCollection serviceCollection = new ServiceCollection();
// Add IAssetBuilder, an instruction to construct one later
serviceCollection.AddSingleton<IAssetBuilder, AssetBuilder>();
// Add IAssetSource, that will construct cache cache
serviceCollection.AddSingleton<IAssetSource>(new AssetCacheSource(o => o.AddResourceCache().AddStringsCache().AddCulturesCache()));
// Add IAssetSource, that adds strings
Dictionary<string, string> strings = new Dictionary<string, string> { { "en:hello", "Hello World!" } };
serviceCollection.AddSingleton<IAssetSource>(new AssetFactory(new StringAsset(strings, LineParameterPrinter.Default)));
// Add delegate to forward IAsset request to IAssetBuilder
serviceCollection.AddSingleton<IAsset>(s => s.GetService<IAssetBuilder>().Build());
// Create service scope
using (ServiceProvider serviceScope = serviceCollection.BuildServiceProvider())
{
// Construct new asset
IAsset asset = serviceScope.GetService<IAsset>();
// Create string key
ILine key = new LineRoot().Key("hello").Culture("en");
// Request string
IString value = asset.GetLine(key).GetString();
// Print result
Console.WriteLine(value);
}
Extension method AddLexicalLocalization() adds IAsset, ILineRoot, ICultureProvider and IAssetBuilder services to IServiceCollection.
// Initialize service collection
IServiceCollection serviceCollection = new ServiceCollection();
// Add IAssetBuilder, ILineRoot and ICulturePolicy to service collection
serviceCollection.AddLexicalLocalization(
addStringLocalizerService: false,
addCulturePolicyService: false,
useGlobalInstance: false,
addCache: true);
// Add dictionary of strings
Dictionary<string, string> strings = new Dictionary<string, string> { { "en:hello", "Hello World!" } };
serviceCollection.AddSingleton<IAssetSource>(new AssetFactory(new StringAsset(strings, LineParameterPrinter.Default)));
// Create service scope
using (ServiceProvider serviceScope = serviceCollection.BuildServiceProvider())
{
// Construct new asset
IAsset asset = serviceScope.GetService<IAsset>();
// Create string key
ILine key = new LineRoot().Key("hello").Culture("en");
// Request string
IString value = asset.GetLine(key).GetString();
// Print result
Console.WriteLine(value);
}
IAssetBuilder is the interface for factory class(es) that instantiate IAssets.
/// <summary>
/// Builder that can create <see cref="IAsset"/> instance(s).
///
/// For dependency injection.
/// </summary>
public interface IAssetBuilder
{
/// <summary>
/// List of asset sources that can construct assets.
/// </summary>
IList<IAssetSource> Sources { get; }
/// <summary>
/// Build language strings.
/// </summary>
/// <returns></returns>
IAsset Build();
}
IAssetSource is the interface for sources that contribute asset(s) to the built result.
/// <summary>
/// Source of assets. Adds resources to builder's list.
/// </summary>
public interface IAssetSource
{
/// <summary>
/// Source adds its <see cref="IAsset"/>s to list.
/// </summary>
/// <param name="list">list to add provider(s) to</param>
/// <returns>self</returns>
void Build(IList<IAsset> list);
/// <summary>
/// Allows source to do post build action and to decorate already built asset.
///
/// This allows a source to provide decoration such as cache.
/// </summary>
/// <param name="asset"></param>
/// <returns>asset or component</returns>
IAsset PostBuild(IAsset asset);
}
Asset Cache
AssetCache is used for caching the requests in cases where asset implementation needs better performance. Asset cache works as a decorator layer that forwards requests to its source and then stores the results.
Asset cache needs to be populated with IAssetCacheParts which each handle caching for a specific interface.
// Create asset
var source = new Dictionary<string, string> { { "Culture:en:Key:hello", "Hello World!" } };
IAsset asset = new StringAsset(source, LineFormat.Parameters);
// Create cache
IAssetCache asset_cached = new AssetCache(asset);
// Adds feature to cache IBinaryAsset specific requests
asset_cached.Add(new AssetCachePartResources(asset_cached.Source, asset_cached.Options));
// Adds feature to cache IStringAsset specific requests
asset_cached.Add(new AssetCachePartStrings(asset_cached.Source, asset_cached.Options));
// Adds feature to cache IAssetCultureEnumerable specific requests
asset_cached.Add(new AssetCachePartCultures(asset_cached.Source, asset_cached.Options));
// Assign the cached asset
LineRoot.Global.Asset = asset_cached;
There are extension methods for convenience.
// Create cache decorator
IAssetCache asset_cached = new AssetCache(asset).AddResourceCache().AddStringsCache().AddCulturesCache();
And then there is one extension method CreateCache() that wraps the asset into a cache and adds the default cache parts.
// Decorate with cache
IAssetCache asset_cached = asset.CreateCache();
IAssetCache is the interface for cache implementatations. It is a composition of cache parts.
/// <summary>
/// Asset cache is decorator that caches requests of source object.
///
/// The interface is used as signal for extension methods.
/// </summary>
public interface IAssetCache : IAssetComposition
{
/// <summary>
/// Source asset.
/// </summary>
IAsset Source { get; }
/// <summary>
/// Cache options.
/// </summary>
AssetCacheOptions Options { get; }
}
/// <summary>
/// Part that addresses a feature (an interface) to cache.
/// </summary>
public interface IAssetCachePart : IAsset
{
}
Caching options
AssetCacheOptions carries a key-value map of caching parameters.
// Create asset
var source = new Dictionary<string, string> { { "Culture:en:Key:hello", "Hello World!" } };
IAsset asset = new StringAsset(source, LineFormat.Parameters);
// Create cache
IAssetCache asset_cached = asset.CreateCache();
// Configure options
asset_cached.Options.SetCloneKeys(true);
asset_cached.Options.SetCacheStreams(true);
asset_cached.Options.SetMaxResourceCount(1024);
asset_cached.Options.SetMaxResourceSize(1024 * 1024);
asset_cached.Options.SetMaxResourceTotalSize(1024 * 1024 * 1024);
// Assign the asset with cache decoration
LineRoot.Global.Asset = asset_cached;
Table of Asset cache option's keys
Key | Method | Default | Description |
---|---|---|---|
CloneKeys | .SetCloneKeys(bool) | true | Should cache create clones of keys, or should it use the keys that come from requests in its cache structures. |
CacheStreams | .SetCacheStreams(bool) | true | Should IBinaryAsset#OpenStream requests be cached. |
MaxResourceCount | .SetMaxResourceCount(int) | 2147483647 | Maximum number of resources to cache. |
MaxResourceSize | .SetMaxResourceSize(int) | 4096 | Maximum size of a resource. |
MaxResourceTotalSize | .SetMaxResourceTotalSize(int) | 1048576 | Maximum total number of bytes to reserve for all cached resources. |
Note
It is implementation specific whether option is supported or not. Some cache options may not be used.
Clearing Cache
IAsset.Reload() clears caches and reloads assets from their configured sources.
// Create asset
var source = new Dictionary<string, string> { { "Culture:en:Key:hello", "Hello World!" } };
IAsset asset = new StringAsset(source, LineFormat.Parameters);
// Cache it
asset = asset.CreateCache();
// Issue a request which will be cached.
ILine key = new LineRoot().Key("hello");
IString value = asset.GetLine( key.Culture("en") ).GetString();
Console.WriteLine(value);
// Clear cache
asset.Reload();
Links
- IAssetComposition
- AssetComposition
- IAssetBuilder
- IAssetSource
- AssetBuilder
- AssetSource Passes IAsset to to builder.
- AssetCacheSource Adds cache to the built asset.
- ResourceManagerStringLocalizerAsset Adapts location of .resources file to IAsset.
- ResourceManagerStringLocalizerAssetSource Adapts location of .resources file to IAssetSource.
- IAssetCache
- AssetCache