【发布时间】:2012-02-02 05:30:24
【问题描述】:
我已经完成了与此相关的 SO 问题,但找不到任何与此问题相关的问题,因此我要问这个问题。
我有一个构建任务(添加为AfterBuild 目标),用于验证类型名称。这些类型名称是来自正在构建的 silverlight 项目的完全限定类型名称。
为了解析这些类型名称,我使用Type.ReflectionOnlyGetType()。为了加载依赖程序集,我处理 AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve 事件以使用 Assembly.ReflectionOnlyLoadFrom(filepath) 从项目输出路径加载项目特定程序集,并从 silverlight 安装路径加载 silverlight 基础程序集。
当我在 VS2010 中构建项目时效果很好,但在我使用 MSBuild 构建时失败,即C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "C:\Root\branches\x.x.x\clients.sln" /t:rebuild /p:Configuration=Debug "/p:Platform=Any CPU" /v:quiet /maxcpucount:1
在使用 MSBuild 构建时,ReflectionOnlyAssemblyResolve 事件会针对 "System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e" 触发,该事件是从 silverlight 安装路径加载的。但是,正在尝试"C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/System.DLL" 中的此系统程序集,但由于主版本不匹配而失败。
以下是我的代码的剥离版本,专门针对这个问题:
public class ValidateTypeTask : Task
{
public override bool Execute()
{
Initialize();
List<string> typeNames = GetTypes();
foreach (var typeName in typeNames)
{
var isResolved = IsResolvable(typeName);
if (!isResolved)
{
return false;
}
}
CleanUp();
return true;
}
private void Initialize()
{
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);
}
Assembly CurrentDomain_ReflectionOnlyAssemblyResolve(object sender, ResolveEventArgs args)
{
Assembly loadedAssembly = null;
Exception loadedException = null;
try
{
loadedAssembly = Assembly.ReflectionOnlyLoad(args.Name);//this will fail always
}
catch (Exception ex)
{
loadedException = ex;
}
if (loadedAssembly != null)
{
return loadedAssembly;
}
string assemblyPath = string.Empty;
var assemblyName = new AssemblyName(args.Name);
if (args.Name.StartsWith("System"))
{
assemblyPath = @"c:\Program Files\Reference Assemblies\Microsoft\Framework\Silverlight\v4.0";
}
else
{
assemblyPath = @"C:\Root\branches\x.x.x\bin\debug";
}
assemblyPath = string.Format(@"{0}\{1}.dll", assemblyPath, assemblyName.Name);
if (File.Exists(assemblyPath))
{
loadedAssembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
}
if (loadedAssembly == null)
{
throw loadedException;
}
return loadedAssembly;
}
private void CleanUp()
{
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= new ResolveEventHandler(CurrentDomain_ReflectionOnlyAssemblyResolve);
}
private List<string> GetTypes()
{
return new List<string>();
}
private bool IsResolvable(string typeName)
{
Type resolvedType = null;
try
{
resolvedType = Type.ReflectionOnlyGetType(typeName, true, true);
}
catch (Exception ex)
{
}
if (resolvedType != null)
{
return true;
}
return false;
}
}
我得到的异常如下:
System.IO.FileLoadException: Could not load file or assembly 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e'
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, Boolean loadTypeFromPartialName, ObjectHandleOnStack type)
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, Boolean loadTypeFromPartialName)
at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
at System.Type.ReflectionOnlyGetType(String typeName, Boolean throwIfNotFound, Boolean ignoreCase)
at in c:\root\x.xx.x\BuildTasks\ValidateTypesTask.cs line xxx
Assembly manager loaded from: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = domain\username
LOG: DisplayName = System, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e
(Fully-specified)
LOG: Appbase = file:///C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This is an inspection only bind.
LOG: Using application configuration file: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\msbuild.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Attempting download of new URL file:///C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/System.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Major Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
我还尝试将 silverlight 程序集路径包含到 AssemblySearchPaths 项目属性中,以使其成为探测 url 的一部分并且仍然相同。
【问题讨论】:
-
尝试更新项目引用或传递 ToolsVersion=2.0
-
@KMoraz 我尝试删除和添加系统程序集引用,只是为了更新项目引用,但这没有帮助。我无法将 ToolsVersion 设置为 2,因为目标是 Silverlight 4.0。另外,我不想设置 ToolsVersion,因为在 VS2010 中一切正常。