Skip to content

Instantly share code, notes, and snippets.

@usausa
Last active February 20, 2019 06:20
Show Gist options
  • Save usausa/5a89726a065c919bf6a9f6cfccb17493 to your computer and use it in GitHub Desktop.
Save usausa/5a89726a065c919bf6a9f6cfccb17493 to your computer and use it in GitHub Desktop.
Static field in generic type with policy
using System;
public interface IPolicy
{
string ToName(string source);
}
public sealed class DefaultPolicy : IPolicy
{
public string ToName(string source) => source;
}
public sealed class LowerPolicy : IPolicy
{
public string ToName(string source) => source.ToLower();
}
public abstract class SeparatorPolicy : IPolicy
{
public sealed class PathPolicy : SeparatorPolicy
{
public PathPolicy() : base(true, "\\")
{
}
}
public sealed class UnderlinePolicy : SeparatorPolicy
{
public UnderlinePolicy() : base(false, "_")
{
}
}
private readonly bool root;
private readonly string separator;
private SeparatorPolicy(bool root, string separator)
{
this.root = root;
this.separator = separator;
}
public string ToName(string source) => (root ? separator : "") + source.Replace(".", separator);
}
public class Metadata
{
public string Name { get; }
public Metadata(string name)
{
Name = name;
}
}
public interface IMetadataFactory
{
Metadata Create<T>();
}
public sealed class StandardMetadataFactory<TPolicy> : IMetadataFactory
where TPolicy : IPolicy
{
private static readonly IPolicy Policy = (IPolicy)Activator.CreateInstance(typeof(TPolicy));
private static class MetadataHolder<T>
{
public static Metadata Value { get; }
static MetadataHolder()
{
Value = new Metadata(Policy.ToName(typeof(T).FullName));
}
}
public Metadata Create<T>()
{
return MetadataHolder<T>.Value;
}
}
public static class MetadataFactories
{
public static IMetadataFactory Default { get; } = new StandardMetadataFactory<DefaultPolicy>();
public static IMetadataFactory Lower { get; } = new StandardMetadataFactory<LowerPolicy>();
public static IMetadataFactory Path { get; } = new StandardMetadataFactory<SeparatorPolicy. PathPolicy>();
public static IMetadataFactory Underline { get; } = new StandardMetadataFactory<SeparatorPolicy.UnderlinePolicy>();
}
public class Component
{
public IMetadataFactory MetadataFactory { get; set; } = MetadataFactories.Default;
public void ShowName<T>()
{
Console.WriteLine(MetadataFactory.Create<T>().Name);
}
}
public static class Program
{
public static void Main()
{
var component = new Component();
// System.String
component.ShowName<string>();
// system.string
component.MetadataFactory = MetadataFactories.Lower;
component.ShowName<string>();
// \System\String
component.MetadataFactory = MetadataFactories.Path;
component.ShowName<string>();
// System_String
component.MetadataFactory = MetadataFactories.Underline;
component.ShowName<string>();
}
}
using System;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Exporters;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using Smart.Collections.Concurrent;
public static class Program
{
public static void Main(string[] args)
{
BenchmarkRunner.Run<Benchmark>();
}
}
public class BenchmarkConfig : ManualConfig
{
public BenchmarkConfig()
{
Add(MarkdownExporter.Default, MarkdownExporter.GitHub);
Add(MemoryDiagnoser.Default);
Add(Job.ShortRun);
}
}
[Config(typeof(BenchmarkConfig))]
public class Benchmark
{
private static readonly Type TypeKey = typeof(object);
private readonly Func<Type, string> factory = x => x.FullName;
private readonly Dictionary<Type, string> dictionary = new Dictionary<Type, string>();
private readonly ThreadsafeTypeHashArrayMap<string> hashArrayMap = new ThreadsafeTypeHashArrayMap<string>();
private readonly IMetadataFactory simpleMetadataFactory = new SimpleMetadataFactory();
private readonly IMetadataFactory policyMetadataFactory = new PolicyMetadataFactory<DefaultPolicy>();
[GlobalSetup]
public void Setup()
{
dictionary[TypeKey] = TypeKey.ToString();
hashArrayMap.AddIfNotExist(TypeKey, TypeKey.ToString());
simpleMetadataFactory.Create<object>();
policyMetadataFactory.Create<object>();
}
[Benchmark]
public string Dictionary()
{
if (!dictionary.TryGetValue(TypeKey, out var name))
{
name = TypeKey.ToString();
dictionary[TypeKey] = name;
}
return name;
}
[Benchmark]
public string DictionaryWithLock()
{
lock (dictionary)
{
if (!dictionary.TryGetValue(TypeKey, out var name))
{
name = TypeKey.ToString();
dictionary[TypeKey] = name;
}
return name;
}
}
[Benchmark]
public string ThreadsafeHashArray()
{
return hashArrayMap.AddIfNotExist(TypeKey, factory);
}
[Benchmark]
public string SimpleMetadataFactory()
{
return simpleMetadataFactory.Create<object>();
}
[Benchmark]
public string PolicyMetadataFactory()
{
return policyMetadataFactory.Create<object>();
}
}
public interface IMetadataFactory
{
string Create<T>();
}
public sealed class SimpleMetadataFactory : IMetadataFactory
{
private static class MetadataHolder<T>
{
public static string Value { get; }
static MetadataHolder()
{
Value = typeof(T).FullName;
}
}
public string Create<T>()
{
return MetadataHolder<T>.Value;
}
}
public interface IPolicy
{
string ToName(string source);
}
public sealed class DefaultPolicy : IPolicy
{
public string ToName(string source) => source;
}
public sealed class PolicyMetadataFactory<TPolicy> : IMetadataFactory
where TPolicy : IPolicy
{
private static readonly IPolicy Policy = (IPolicy)Activator.CreateInstance(typeof(TPolicy));
private static class MetadataHolder<T>
{
public static string Value { get; }
static MetadataHolder()
{
Value = Policy.ToName(typeof(T).FullName);
}
}
public string Create<T>()
{
return MetadataHolder<T>.Value;
}
}
Method Mean Error StdDev
Dictionary 18.28 ns 3.178 ns 0.1742 ns
DictionaryWithLock 31.25 ns 39.024 ns 2.1390 ns
ThreadsafeHashArray 21.99 ns 4.916 ns 0.2694 ns
SimpleMetadataFactory 16.85 ns 2.537 ns 0.1391 ns
PolicyMetadataFactory 17.56 ns 1.543 ns 0.0846 ns
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment