How do you list your referenced solution assemblies for IoC registration? I was really tired of typing something strange as new [] { typeof(SomeType).Assembly, ... }
. What do you think about the following approach?
Use case:
class Program
{
static void Main(string[] args)
{
foreach (var a in Solution.Assemblies)
Console.WriteLine(a);
}
}
Where Solution.Assemblies
is:
public static class Solution
{
static IEnumerable<string> AssemblyNames => new[] {
"ValueCache", "ValueCache.Tests", "LazyProxies", "ConsoleApplication1", "ClassLibrary1"
};
public static IEnumerable<Assembly> Assemblies => AssemblyNames
.Select(an => Load(an))
.Where(a => a != null);
[DebuggerHidden]
static Assembly Load(string assemblyName)
{
try
{
return Assembly.Load(new AssemblyName(assemblyName));
}
catch
{
return null;
}
}
}
... being generated by Solution.tt
file:
<#@ template debug="false" hostSpecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDte" #>
<#@ import namespace="System" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
namespace SolutionConfiguration
{
public static class Solution
{
static IEnumerable<string> AssemblyNames => new[] {
<#= String.Join(", ", from name in new SolutionAssemblyNames(Host)
select $"\"{name}\"") #>
};
public static IEnumerable<Assembly> Assemblies => AssemblyNames
.Select(an => Load(an))
.Where(a => a != null);
[DebuggerHidden]
static Assembly Load(string assemblyName)
{
try
{
return Assembly.Load(new AssemblyName(assemblyName));
}
catch
{
return null;
}
}
}
}
<#+
class SolutionAssemblyNames : IEnumerable<string>
{
public SolutionAssemblyNames(ITextTemplatingEngineHost host)
{
Host = host;
}
public IEnumerator<string> GetEnumerator() => Assemblies.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerable<string> Assemblies => Projects
.Select(p => p?.Properties?.Item("AssemblyName")?.Value as string)
.Distinct().Where(a => !string.IsNullOrWhiteSpace(a));
IEnumerable<Project> Projects => VisualStudio.Solution.Projects.OfType<Project>();
DTE VisualStudio => (Host as IServiceProvider).GetService(typeof(DTE)) as DTE;
ITextTemplatingEngineHost Host { get; }
}
#>
1 Answer 1
This is a fascinating solution. I kept looking at it and thinking "There must be an easier way!" but every possible solution I came up with had a fatal flaw.
All I really have, then, is nitpicking:
public static IEnumerable<Assembly> Assemblies => AssemblyNames
.Select(an => Load(an))
Can be simplified to:
public static IEnumerable<Assembly> Assemblies => AssemblyNames
.Select(Load)
SolutionAssemblyNames
is looking fairly dense. I'd add 1 line of whitespace between each property to make it a bit more readable.