假设我有一个包含4个项目的解决方案,A,A_UnitTests,B和B_UnitTests。
项目A有一个数据文件,该文件作为链接添加到A_UnitTests并设置为复制到输出目录。运行单元测试或在生产中执行代码时,使用以下代码片段正确识别该文件的路径:
public static string GetFullPath(string relativePath)
{
string retVal = string.Empty;
if (System.Web.HttpContext.Current == null)
{
string locationBeforeShadowCopy = typeof(A.SomeClassInA).Assembly.CodeBase;
UriBuilder uri = new UriBuilder(locationBeforeShadowCopy);
string locationWithoutUriPrefixes = Uri.UnescapeDataString(uri.Path);
string dir = Path.GetDirectoryName(locationWithoutUriPrefixes);
retVal = Path.Combine(dir, relativePath);
}
else
{
// stuff that doesn't matter
}
return retVal;
}
但是,我在B_UnitTests中有一个新的测试用例,它尝试使用此代码路径来查找文件位置。但是,即使我调用typeof(A.SomeClassInA).Assembly.CodeBase
,也会使用其引用的DLL从B_UnitTests调用它。这意味着路径返回是B_UnitTests输出目录+相对路径。所以它找不到数据文件。
不使用硬编码设置和构建脚本,我可以使用什么来指定正确的路径?
更新(澄清) 真正的问题是typeForClassInA.Assembly.CodeBase返回执行程序集的路径而不是A本身。提供来自某个程序集的类型似乎非常错误,但它不返回原始程序集位置,而是返回执行程序集的路径,该路径恰好具有对它的引用。
答案 0 :(得分:1)
If there is a reference to 'typeForClassInA', then its assembly will be being copied into the output directory of B_UnitTests. So when you ask for CodeBase of that type's assembly from a test in B_UnitTests, it is (correctly) pointing at the version of assembly A in the B_UnitTests output folder, because that's where it's being loaded from.
I admit that I avoid using Shadow Copy to avoid exactly these kinds of problems of locating resources which are alongside the assembly, since ShadowCopy doesn't understand that they are needed, and they don't get shadow copied.
Another thing which can help is to build all the projects into the same output folder by changing all the project output folders to be "..\bin". For example, this would mean that A_UnitTests would not need the link to the resource file (once shadow copy is off).
I have a method similar to the one you've shown which goes "up" from the assembly's location (which for me is the shared bin folder) to the solution's location; and my relative paths are 'rooted' at that folder.
If that all sounds too complex, you could just use the same approach that A_UnitTests did, of including a link to it from B_UnitTests.