是否有可能实现像单元测试中那样的行为 您无法在其中注释的地方
[TestInitialize]
每次在
之前执行此功能[TestMethod]
被执行。并且以相同的方式
[TestCleanup]
总是在TestMethod之后执行。
答案 0 :(得分:2)
您不能开箱即用。您需要编写自己的执行代码,该代码使用反射来确定执行的内容和方式。下面,我将分享一个简单的示例。
首先,您需要使用属性来描述方法的类型。
class InitMethodAttribute : Attribute
{
public InitMethodAttribute():base()
{ }
};
class CleanupMethodAttribute : Attribute
{
public CleanupMethodAttribute() : base()
{ }
};
class RunMethodAttribute : Attribute
{
public RunMethodAttribute() : base()
{ }
};
我们将在示例类中使用它。请注意,此示例中的所有方法都是私有的。可以通过反射来调用它们。另外,请注意,为简单起见,它们没有参数,也不返回任何内容。您可以解决此示例,并将其更改为也支持参数。
class Example
{
[InitMethod]
private void Init()
{
Console.WriteLine("Initializing...");
}
[InitMethod]
private void InitMore()
{
Console.WriteLine("More initializing...");
}
[RunMethod]
private void Run()
{
Console.WriteLine("Running...");
}
[CleanupMethod]
private void Cleanup()
{
Console.WriteLine("Cleaning up...");
}
}
下一类称为执行程序(executor),它获取一个对象并查看其类型,识别方法并查看其属性。最终,如果在任何方法上都找到了RunMethod
属性,则该方法将被执行。在执行所有InitMethod
装饰方法之前,以及在所有CleanupMethod
装饰方法之后。
static class Executor
{
public static void Run(object obj)
{
var type = obj.GetType();
var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
var initMethods = new List<MethodInfo>();
var cleanMethods = new List<MethodInfo>();
foreach (var method in methods)
{
var initattrs = method.GetCustomAttributes(typeof(InitMethodAttribute));
var cleanattrs = method.GetCustomAttributes(typeof(CleanupMethodAttribute));
if (initattrs != null && initattrs.Count() > 0)
initMethods.Add(method);
else if (cleanattrs != null && cleanattrs.Count() > 0)
cleanMethods.Add(method);
}
foreach (var method in methods)
{
var runattrs = method.GetCustomAttributes(typeof(RunMethodAttribute));
if(runattrs != null)
{
var runattr = runattrs.FirstOrDefault();
if(runattr != null)
{
foreach (var m in initMethods)
m.Invoke(obj, null);
method.Invoke(obj, null);
foreach (var m in cleanMethods)
m.Invoke(obj, null);
}
}
}
}
}
以下程序将使用所有这些内容:
class Program
{
static void Main(string[] args)
{
var example = new Example();
Executor.Run(example);
}
}
输出为:
Initializing...
More initializing...
Running...
Cleaning up...
答案 1 :(得分:0)
您要查找的内容称为Aspect Oriented Programming,但不幸的是(或不取决于您询问的人),C#没有实现任何本机机制来支持它。实现AOP引擎当然是可能的,但不是一件容易的事,您需要使用某种动态代理(相关问题:CodeConstruct和.NET Core: attributes that execute before and after method指出的How to make a simple dynamic proxy in C#;还有here's a nice article about the subject)。
答案 2 :(得分:0)
有两种替代解决方案。
其中之一是,您可以使用Template Methods,其中初始化和清除是在基类中定义的,而实现类仅实现DoWorkImpl
方法。调用DoWork
会调用Initialize
,然后运行在继承类中实现的DoWorkImpl
方法,并以Cleanup
结尾。这在(伪)代码中看起来像这样:
public abstract class BaseClass
{
public void DoWork()
{
Initialize();
DoWorkImpl();
CleanUp();
}
public abstract void DoWorkImpl();
private void Initialize()
{
// Initialization code here.
}
private void Cleanup()
{
// Cleanup code here.
}
}
另一种替代方法是使用Actions。
这在(伪)代码中看起来像这样:
public void SurroundWithInitializeAndCleanup(Action actionToWrap)
{
Initialize();
actionToWrap();
Cleanup();
}
private void Initialize()
{
// Initialization code here.
}
private void Cleanup()
{
// Cleanup code here.
}