如何在设计时获取C#类文件的父目录路径?
问题描述
技术开发环境
- .NET Core 3.1
- PostgreSQL 14.2(由Visual C++ build 1914编译,64位)
- EntityFramework.Functions Version=1.5.0
- Microsoft.EntityFrameworkCore.Design Version=5.0.17
- Microsoft.EntityFrameworkCore.Tools Version=5.0.17
- Npgsql.EntityFrameworkCore.PostgreSQL Version=5.0.10
场景与问题
C#代码文件JohnDoeCSharp.cs位于VisualStudioProjectDir\Migrations\1.0.5目录下,构造函数代码如下:
public class JohnDoeCSharp { public JohnDoeCSharp() { } }
希望在构造函数中获取父目录名称“1.0.5”,但使用以下代码返回的是运行时目录路径,无法满足需求:
string strExeFilePath =
System.Reflection.Assembly.GetExecutingAssembly().Location;string strWorkPath = System.IO.Path.GetDirectoryName(strExeFilePath);
需要获取设计时/编码时的目录路径值,该如何操作?
解决方案
编译后程序集的运行时路径与编码时的源文件目录完全分离,因此不能通过Assembly.GetExecutingAssembly().Location获取源文件目录。以下是两种可靠的实现方式:
1. 编译时常量注入源文件路径
在项目的.csproj文件中添加编译常量,直接将目标目录路径注入到代码中:
<PropertyGroup> <DefineConstants>$(DefineConstants);SOURCE_DIRECTORY=$(MSBuildThisFileDirectory)Migrations\1.0.5</DefineConstants> </PropertyGroup>
之后在代码中直接使用该常量提取目录名称:
public class JohnDoeCSharp { public JohnDoeCSharp() { string versionDir = System.IO.Path.GetFileName(SOURCE_DIRECTORY); // 得到"1.0.5" } }
注意:若后续文件目录结构变动,需同步更新项目文件中的常量值。
2. 通过项目根目录动态推导(更灵活)
如果不想硬编码目录路径,可通过在项目根目录放置标记文件(如_ProjectRootMarker.txt),以此定位项目根目录后拼接目标路径:
public class JohnDoeCSharp { public JohnDoeCSharp() { string currentDir = System.IO.Directory.GetCurrentDirectory(); // 向上遍历直到找到项目根目录的标记文件 while (!System.IO.File.Exists(System.IO.Path.Combine(currentDir, "_ProjectRootMarker.txt"))) { currentDir = System.IO.Path.GetDirectoryName(currentDir); if (string.IsNullOrEmpty(currentDir)) break; } // 拼接得到目标目录并提取名称 string targetDir = System.IO.Path.Combine(currentDir, "Migrations", "1.0.5"); string versionDir = System.IO.Path.GetFileName(targetDir); // 得到"1.0.5" } }
这种方式适配目录结构变动的场景,只需保证标记文件始终在项目根目录即可。
区分设计时与运行时环境
设计时(如EF迁移工具执行时)的当前目录通常为项目根目录,而运行时目录不同,可通过EF的设计时判断API区分:
using Microsoft.EntityFrameworkCore.Design; public class JohnDoeCSharp { public JohnDoeCSharp() { string rootDir; // 判断是否处于设计时环境 if (DesignTimeServicesBuilder.IsDesignTime) { rootDir = System.IO.Directory.GetCurrentDirectory(); } else { // 运行时使用程序集目录或其他配置逻辑 rootDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location); } string targetDir = System.IO.Path.Combine(rootDir, "Migrations", "1.0.5"); string versionDir = System.IO.Path.GetFileName(targetDir); } }
内容的提问来源于stack exchange,提问作者crazyTech
相关产品推荐
相关产品推荐

