public static Func <TInstance, TProperty> GetGetter(string propertyName)
    {
        if (!Getters.TryGetValue(propertyName, out Func <TInstance, TProperty> getter))
        {
            getter = FastPropertyFactory.GeneratePropertyGetter <TInstance, TProperty>(propertyName);
            Getters[propertyName] = getter;
        }

        return(getter);
    }
    public static Action <TInstance, TProperty> GetSetter(string propertyName)
    {
        if (!Setters.TryGetValue(propertyName, out Action <TInstance, TProperty> setter))
        {
            setter = FastPropertyFactory.GeneratePropertySetter <TInstance, TProperty>(propertyName);
            Setters[propertyName] = setter;
        }

        return(setter);
    }
    public static void Main(params string[] args)
    {
        var stepCount = 5000000UL;

        var dummy = new Dummy();

        const string propertyName = "Soother";

        const bool propertyValue = true;

        var propertyInfo = typeof(Dummy).GetProperty(propertyName);

        var lambdaExpression = FastPropertyFactory.GeneratePropertySetter <Dummy, bool>(propertyName);

        var nativeBenchmark                     = Benchmark.Run("Native", stepCount, () => dummy.Soother = propertyValue);
        var lambdaExpressionBenchmark           = Benchmark.Run("Lambda Expression", stepCount, () => lambdaExpression(dummy, propertyValue));
        var dictionaryLambdaExpressionBenchmark = Benchmark.Run("Dictionary Access + Lambda Expression", stepCount, () => dummy.Set(propertyName, propertyValue));
        var propertyInfoBenchmark               = Benchmark.Run("Property Info", stepCount, () => propertyInfo.SetValue(dummy, propertyValue, null));

        var benchmarkReports = new[]
        {
            nativeBenchmark,
            lambdaExpressionBenchmark,
            dictionaryLambdaExpressionBenchmark,
            propertyInfoBenchmark
        }.OrderBy(item => item.ElapsedMilliseconds);

        benchmarkReports.Join(Environment.NewLine).WriteLineToConsole();

        var fastest = benchmarkReports.First().ElapsedMilliseconds;

        benchmarkReports.Select(report => (report.ElapsedMilliseconds / fastest).ToString("0.000")).Join(" < ").WriteLineToConsole();

        var dictionaryAccess = (dictionaryLambdaExpressionBenchmark.ElapsedMilliseconds / lambdaExpressionBenchmark.ElapsedMilliseconds * 100);

        ("Dictionary Access: " + dictionaryAccess + " %").WriteLineToConsole();

        Console.ReadKey();
    }