/Code/Source/Teaching.Core/Cli/CliSampleApplication.cs
C# | 147 lines | 117 code | 27 blank | 3 comment | 9 complexity | 1181c3befa5ad89c37d3711c85aa3f9d MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.Composition;
- using System.ComponentModel.Composition.Hosting;
- using System.ComponentModel.Composition.Primitives;
- using System.Diagnostics;
- using System.Diagnostics.Contracts;
- using System.Globalization;
- using System.IO;
- using System.Linq;
- using System.Reflection;
- using Teaching.Core.Profiling;
-
- namespace Teaching.Core.Cli
- {
- public sealed class CliSampleApplication
- {
- private readonly IEnumerable<Assembly> assemblies;
- private readonly TextWriter output;
-
- [ImportMany]
- private IEnumerable<Lazy<ICliSample, ICliSampleMetadata>> Samples { get; set; }
-
- public int Run(IEnumerable<string> arguments)
- {
- Contract.Requires<ArgumentNullException>( arguments != null,"arguments");
-
- var cliParser = new CliParser(arguments);
-
- output.WriteLine("Scanning the following assemblies for samples");
- foreach( var assembly in assemblies)
- {
- output.WriteLine(assembly);
- }
-
- var catalog = new AggregateCatalog(assemblies.Select(a => new AssemblyCatalog(a)));
-
- using( var container = new CompositionContainer(catalog) )
- {
- var batch = new CompositionBatch();
-
- batch.AddExportedValue(container);
- batch.AddExportedValue(catalog);
- batch.AddExportedValue(output);
- batch.AddExportedValue<ICliParser>(cliParser);
-
- container.Compose(batch);
-
- // This is not supported now, so we have to resort to an internal import
- //var samples = container.GetExportedValues<Lazy<ICliSample, ICliSampleMetadata>>().ToList();
- container.SatisfyImportsOnce(this);
-
- var sampleToRun = FindSample(cliParser.GetArgument("sample",string.Empty));
- var result = -1;
-
- if (sampleToRun == null)
- {
- output.WriteLine("No sample selected to execute on the command line");
- output.WriteLine();
-
- OutputLegend(Samples);
- output.WriteLine();
- output.WriteLine("Select sample to run interactivly by name or index: ");
-
- sampleToRun = FindSample(Console.ReadLine());
- output.WriteLine();
- }
-
- if ( sampleToRun != null )
- {
- result = ExecuteSample(sampleToRun);
- }
-
- if ( Debugger.IsAttached )
- {
- Console.ReadKey();
- }
-
- return result;
- }
- }
-
- private int ExecuteSample(Lazy<ICliSample,ICliSampleMetadata> sample)
- {
- output.WriteLine("Executing sample {0}",sample.Metadata.Name);
-
- // Force evaluation to finish initialization:
- var sampleInstance = sample.Value;
-
- using (new ProfiledSection(output, "Sample {1} executed in {0}", sample.Metadata.Name))
- {
- if (!Debugger.IsAttached)
- {
- try
- {
- sampleInstance.Execute();
- }
- catch (Exception ex)
- {
- output.WriteLine("An exception occured in sample {0}", sample.Metadata.Name);
- output.WriteLine(ex);
-
- return -1;
- }
- }
- else
- {
- sampleInstance.Execute();
- }
- }
-
- return 0;
- }
-
- private void OutputLegend(IEnumerable<Lazy<ICliSample,ICliSampleMetadata>> samples )
- {
- foreach( var sampleGroup in samples.GroupBy(s => s.Metadata.Index))
- {
- if ( sampleGroup.Count() > 1)
- {
- output.WriteLine("Sample {0} is duplicated",sampleGroup.Key);
- }
- }
-
- output.WriteLine("Available samples: ({0}) in total",samples.Count());
- output.WriteLine("");
-
- foreach( var sample in samples.OrderBy(s => s.Metadata.Index) )
- {
- output.WriteLine("{0}. {1} - {2}",sample.Metadata.Index,sample.Metadata.Name,sample.Metadata.Description);
- }
- }
-
- private Lazy<ICliSample,ICliSampleMetadata> FindSample(string selection)
- {
- return Samples.FirstOrDefault(s => s.Metadata.Index.ToString(CultureInfo.InvariantCulture) == selection) ??
- Samples.FirstOrDefault(
- s => s.Metadata.Name.Equals(selection, StringComparison.OrdinalIgnoreCase));
- }
-
- public CliSampleApplication(IEnumerable<Assembly> assemblies = null,TextWriter output = null)
- {
- this.assemblies = assemblies ?? new[] {Assembly.GetEntryAssembly()};
- this.output = output ?? Console.Out;
- }
- }
- }