public static IEnumerable<Benchmark> TypeToBenchmarks(Type type) { var methods = type.GetMethods(); var setupMethod = methods.FirstOrDefault(m => m.ResolveAttribute<SetupAttribute>() != null); if (setupMethod != null) { // setupMethod is optional, but if it's there it must have the correct signature, accessibility, etc AssertMethodHasCorrectSignature("Setup", setupMethod); AssertMethodIsAccessible("Setup", setupMethod); AssertMethodIsNotGeneric("Setup", setupMethod); } // If there is one, get the single Field or Property that has the [Params(..)] attribute var reflectionFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; var fields = type.GetFields(reflectionFlags).Select(f => new { f.Name, Attribute = f.ResolveAttribute<ParamsAttribute>(), Private = f.IsPrivate, IsStatic = f.IsStatic, }); var properties = type.GetProperties(reflectionFlags).Select(p => new { p.Name, Attribute = p.ResolveAttribute<ParamsAttribute>(), Private = p.GetSetMethod() == null ? true : false, IsStatic = p.GetSetMethod() != null ? p.GetSetMethod().IsStatic : false }); var fieldOrProperty = fields.Concat(properties).FirstOrDefault(i => i.Attribute != null); var privateField = fields.FirstOrDefault(f => f.Attribute != null && f.Private); if (privateField != null) throw new InvalidOperationException($"Field \"{privateField.Name}\" must be public if it has the [Params(..)] attribute applied to it"); var privateProperty = properties.FirstOrDefault(p => p.Attribute != null && p.Private); if (privateProperty != null) throw new InvalidOperationException($"Property \"{privateProperty.Name}\" must be public and writable if it has the [Params(..)] attribute applied to it"); for (int i = 0; i < methods.Length; i++) { var methodInfo = methods[i]; var benchmarkAttribute = methodInfo.ResolveAttribute<BenchmarkAttribute>(); if (benchmarkAttribute != null) { var target = new BenchmarkTarget(type, methodInfo, setupMethod, benchmarkAttribute.Description); AssertMethodHasCorrectSignature("Benchmark", methodInfo); AssertMethodIsAccessible("Benchmark", methodInfo); AssertMethodIsNotGeneric("Benchmark", methodInfo); foreach (var task in BenchmarkTask.Resolve(methodInfo)) { if (fieldOrProperty == null) { yield return new Benchmark(target, task); } else { var parametersSets = new BenchmarkParametersSets(fieldOrProperty.Name, fieldOrProperty.IsStatic, fieldOrProperty.Attribute.Args); // All the properties of BenchmarkTask and it's children are immutable, so cloning a BenchmarkTask like this should be safe var newTask = new BenchmarkTask(task.ProcessCount, task.Configuration, parametersSets); yield return new Benchmark(target, newTask); } } } } }
public BenchmarkTask(int processCount, BenchmarkConfiguration configuration, BenchmarkParametersSets parametersSets = null) { ProcessCount = processCount; Configuration = configuration; ParametersSets = parametersSets ?? BenchmarkParametersSets.Empty; }
public static IEnumerable<Benchmark> TypeToBenchmarks(Type type) { var methods = type.GetMethods(); var setupMethod = methods.FirstOrDefault(m => m.ResolveAttribute<SetupAttribute>() != null); if (setupMethod != null) { // setupMethod is optional, but if it's there it must have the correct signature, accessibility, etc AssertMethodHasCorrectSignature("Setup", setupMethod); AssertMethodIsAccessible("Setup", setupMethod); AssertMethodIsNotGeneric("Setup", setupMethod); } // If there is one, get the single Field or Property that has the [Params(..)] attribute var fields = type.GetFields().Select(f => new { f.Name, Attribute = f.ResolveAttribute<ParamsAttribute>(), IsStatic = f.IsStatic, }); var properties = type.GetProperties().Select(f => new { f.Name, Attribute = f.ResolveAttribute<ParamsAttribute>(), IsStatic = f.GetSetMethod().IsStatic }); var fieldOrProperty = fields.Concat(properties).FirstOrDefault(i => i.Attribute != null); for (int i = 0; i < methods.Length; i++) { var methodInfo = methods[i]; var benchmarkAttribute = methodInfo.ResolveAttribute<BenchmarkAttribute>(); if (benchmarkAttribute != null) { var target = new BenchmarkTarget(type, methodInfo, setupMethod, benchmarkAttribute.Description); AssertMethodHasCorrectSignature("Benchmark", methodInfo); AssertMethodIsAccessible("Benchmark", methodInfo); AssertMethodIsNotGeneric("Benchmark", methodInfo); foreach (var task in BenchmarkTask.Resolve(methodInfo)) if (fieldOrProperty == null) { yield return new Benchmark(target, task); } else { var parametersSets = new BenchmarkParametersSets(fieldOrProperty.Name, fieldOrProperty.IsStatic, fieldOrProperty.Attribute.Args); // All the properties of BenchmarkTask and it's children are immutable, so cloning a BenchmarkTask like this should be safe var newTask = new BenchmarkTask(task.ProcessCount, task.Configuration, parametersSets); yield return new Benchmark(target, newTask); } } } }