我有两个这样的类:
public class test1: BaseClass
{
public test1() : base()
{
}
...
public class BaseClass
{
public BaseClass(
[CallerMemberName]string membername ="",
[CallerFilePath] string path = "")
{
var sf = new System.Diagnostics.StackTrace(1).GetFrame(0);
}
如果我用对基的调用指定test1
构造函数,我会正确初始化membername
和path
,但如果不是,编译器会生成默认的构造函数调用,并且membername
和path
都为空。
这是bug还是功能?
(Visual Studio 2019 16.11.8,net core 3.1或net 5.0(。
这可能是预期行为,因为编译器生成的默认构造函数调用将显式传入您在可选参数中指定的值(即空字符串(。所以,如果你有这样的东西:
public BaseClass(
[CallerMemberName]string membername = "default-member-name",
[CallerFilePath] string path = "default-path")
{
var sf = new System.Diagnostics.StackTrace(1).GetFrame(0);
}
然后这个代码。。。
public class test1 : BaseClass
{
public test1()
{
}
}
转换为:
public class test1 : BaseClass
{
public test1()
: base("default-member-name", "default-path")
{
}
}
我在谷歌上搜索了"c#编译器github";最后https://github.com/dotnet/roslyn
经过CallerMemberName
搜索,我找到了这个问题的答案:
https://github.com/dotnet/roslyn/issues/53757
它提到这是通过设计完成的。
但快速浏览门票让我想到——";我可以将属性用于相同的目的吗">
由于我所做的是单元测试,我为此重新编码了自己的属性:TestAttribute
=>FactAttribute
并从NUnit方法信息中解析出该属性,并返回文件路径和方法名。
public class FactAttribute : TestAttribute
{
public string FunctionName { get; }
public string FilePath { get; }
public FactAttribute( [CallerMemberName] string functionName = "", [CallerFilePath] string filePath = "")
{
FunctionName = functionName;
FilePath = filePath;
}
}
[TestFixture]
public class BaseClass
{
/// <summary>
/// Accesses private class type via reflection.
/// </summary>
/// <param name="_o">input object</param>
/// <param name="propertyPath">List of properties in one string, comma separated.</param>
/// <returns>output object</returns>
object getPrivate(object _o, string propertyPath)
{
object o = _o;
var flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
foreach (var name in propertyPath.Split('.'))
{
System.Type type = o.GetType();
if (char.IsUpper(name[0]))
o = type.GetProperty(name, flags).GetValue(o);
else
o = type.GetField(name, flags).GetValue(o);
}
return o;
}
[SetUp]
public void EachSpecSetup()
{
var mi = (MemberInfo)getPrivate(TestContext.CurrentContext.Test, "_test.Method.MethodInfo");
FactAttribute attr = mi.GetCustomAttribute<FactAttribute>();
string path = attr.FilePath;
string funcName = attr.FunctionName;
}
这允许确定从哪个文件和从哪个方法调用定向。