因此,在一些实例中,我希望能够做到这一点,但实际上,我希望能够将对超类的所有调用包装在派生类型中。现在,我正在尝试将对基本方法的所有调用包装在Impersonator中,但是我也可以看到其他用途。
一个例子是
public void CopyFile(string filePath, string destPath)
{
using(var I = new Impersonator("user", ".", "password"))
{
base.CopyFile(string filePath, string destPath);
}
}
另一个方便的用法可能是
public void CopyFile(string filePath, string destPath)
{
try
{
base.CopyFile(string filePath, string destPath);
} catch(Exception e)
{
Log(e.Message);
}
}
现在,我想类似地包装所有基本调用。有没有方便的方法可以做到这一点,还是我必须手动包装所有这些?
我正在寻找类似“超类中的foreach baseMethod这样做”的内容
也许找到某种方法来捕获对类的传入调用并将它们包装为一个动作?
public void ActionWrapper(Action action)
{
try
{
action.Invoke();
} catch(Exception e)
{
Log(e.Message);
}
}
但是,我将如何以这种方式接听班级的电话?
老实说,这只是为了使类更具可维护性,并减少代码膨胀。我愿意接受这些或任何其他方法。
首先,我要为您以这种方式解构代码的本能鼓掌。将诸如错误处理/日志记录和安全性/身份之类的关注点与业务逻辑分开,可以为可维护性带来奇迹。
您所描述的被称为装饰或拦截。Mark Seemann在一篇不错的博客文章中比较了日志记录环境中的两种方法。
在不使用外部工具(例如DI或AOP框架)的情况下,我认为ActionWrapper
您提出的方法是一个好的开始。我修改了它以显示模拟而不是记录,因为我认为模拟是一个更有趣的用例:
public void ActionWrapper(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
所以问题是:如何有效地应用此方法?
假设您现有的课程是:
public class FileCopier
{
public void CopyFile(string filePath, string destPath)
{
// Do stuff
}
}
如您所建议,您可以创建派生类以添加模拟:
public class FileCopierWithImpersonation : FileCopier
{
public void CopyFile(string filePath, string destPath)
=> WithImpersonation(base.CopyFile(filePath, destPath));
public void WithImpersonation(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
}
在此,FileCopierWithImpersonation
充当FileCopier
通过继承实现的装饰器。该WithImpersonation
方法用作拦截器,可以将模拟作用域应用于任何方法。
这应该工作得足够好,但是会在实现上造成一些折衷。基类的方法都需要标记为virtual
。子类的构造函数可能需要将参数传递给基类。独立于基类的逻辑不可能对子类的逻辑进行单元测试。
因此,您可能希望提取一个接口(IFileCopier
)并使用组成而不是继承来应用装饰器:
public class FileCopierWithImpersonation : IFileCopier
{
private readonly IFileCopier _decoratee;
public FileCopierWithImpersonation(IFileCopier decoratee)
{
// If you don't want to inject the dependency, you could also instantiate
// it here: _decoratee = new FileCopier();
_decoratee = decoratee;
}
public void CopyFile(string filePath, string destPath)
=> WithImpersonation(_decoratee.CopyFile(filePath, destPath));
public void WithImpersonation(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
}
如果您使用的是Visual Studio 2019,则有一个``通过...实现接口''的重构选项,它将通过调用相同类型的依赖项的方法来自动实现接口。在那之后,添加拦截器只需要简单的查找/替换即可。
您还可以研究代码生成工具,例如T4模板,以自动生成装饰器。但是请注意,.NET Core不支持T4。在这一点上,它似乎是一项遗留技术。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句