我有以下情况:
一个主机应用程序,托管(win)表单,这些表单在同一解决方案的其他项目中定义。托管表单都实现了相同的界面。由于主机应用程序引用了所有其他项目,因此不涉及(并且不需要)动态加载(汇编解析)。
现在我认为我可以迭代AppDomain.CurrentDomain.GetAssemblies()
,获取所有类型并过滤哪些类型实现我的界面。但由于我从未明确使用主机项目中的其他项目,因此程序集将不会加载到主机应用程序中,因此AppDomain.CurrentDomain.GetAssemblies()
将不会列出它们。
我认为在大多数情况下这种行为是好的,但在我的情况下(反射使用),这是一个问题。有没有办法强制加载(特定)引用但未明确使用的程序集?我正在寻找视觉工作室/项目设置方式来做到这一点 - 我不喜欢编写代码来获取已经引用的程序集的想法:(
可能的解决方案:
Assembly.Load
。 con:主机应用中的代码更改答案 0 :(得分:2)
根据 TnTinMn 的评论回答。谢谢你的建议!
Program
类(主机应用的入口点)更改为partial
类Program.AssemblyLoader.tt
Program.AssemblyLoader.tt
:
<#@ template language="C#" hostSpecific="true" debug="True" #>
<#@ output extension="cs" #>
<#@ assembly name="System.Core" #>
<#@ assembly name="EnvDte" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Text.RegularExpressions" #>
<#@ import namespace="System" #>
<#
var visualStudio = (EnvDTE.DTE)(Host as IServiceProvider).GetService(typeof(EnvDTE.DTE));
var solution = (EnvDTE.Solution)visualStudio.Solution;
var projects = solution.Projects;
// Assume that the first item is the main project, the host app.
// Index is **NOT** zero-based!
var main = (EnvDTE.Project)projects.Item(1);
var p = main.Properties.Item("DefaultNamespace");
var ns = p.Value.ToString();
#>
using System;
using System.Linq;
using System.IO;
using System.Reflection;
namespace <# WriteLine(ns); #>
{
static partial class Program
{
static Program()
{
//! Generated file. Do not edit. Check the .tt file instead!
<#
foreach(EnvDTE.Project proj in projects)
{
if(proj.Properties == null || proj.Properties.Item("OutputFileName") == null)
continue;
EnvDTE.Property p2 = proj.Properties.Item("OutputFileName") as EnvDTE.Property;
WriteLine(" LoadAssemblyIfNecessary(\"" + p2.Value + "\");");
}
#>
}
private static readonly AssemblyName[] REFS = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
private static readonly string APP = Path.GetFileName(System.Windows.Forms.Application.ExecutablePath);
private static void LoadAssemblyIfNecessary(string name)
{
if (string.Equals(name, APP, StringComparison.InvariantCultureIgnoreCase)) return;
if (!REFS.Any(x => x.Name.StartsWith(Path.GetFileNameWithoutExtension(name), StringComparison.InvariantCultureIgnoreCase)))
{
AppDomain.CurrentDomain.Load(Path.GetFileNameWithoutExtension(name));
}
}
}
}
生成的Program.AssemblyLoader.cs
:
using System;
using System.Linq;
using System.IO;
using System.Reflection;
namespace Your.Name.Space
{
static partial class Program
{
static Program()
{
//! Generated file. Do not edit. Check the .tt file instead!
LoadAssemblyIfNecessary("HostApp.dll");
LoadAssemblyIfNecessary("Dependency1.dll");
LoadAssemblyIfNecessary("Dependency2.dll");
LoadAssemblyIfNecessary("Modul1.exe");
}
private static readonly AssemblyName[] REFS = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
private static readonly string APP = Path.GetFileName(System.Windows.Forms.Application.ExecutablePath);
private static void LoadAssemblyIfNecessary(string name)
{
if (string.Equals(name, APP, StringComparison.InvariantCultureIgnoreCase)) return;
if (!REFS.Any(x => x.Name.StartsWith(Path.GetFileNameWithoutExtension(name), StringComparison.InvariantCultureIgnoreCase)))
{
AppDomain.CurrentDomain.Load(Path.GetFileNameWithoutExtension(name));
}
}
}
}