C# 抽象类的参数验证
我有以下抽象类:C# 抽象类的参数验证,c#,validation,arguments,abstract,C#,Validation,Arguments,Abstract,我有以下抽象类: public abstract class FileClient { public abstract File GetFile(string Path); public abstract Task<File> GetFileAsync(string Path); public abstract void MoveFile(string Source, string Destination); } 对所有派生类执行上述参数验证的最佳方法
public abstract class FileClient {
public abstract File GetFile(string Path);
public abstract Task<File> GetFileAsync(string Path);
public abstract void MoveFile(string Source, string Destination);
}
对所有派生类执行上述参数验证的最佳方法是什么?我个人可以想到以下方法,请随意提及其他方法
1.在每个派生类中执行验证
我个人不喜欢这个解决方案,因为代码重复
2.实施验证方法
在实用程序类或抽象类本身中实现验证方法,并在每个派生类中调用这些验证方法。我不喜欢这一点,因为我想验证的每个现有方法都需要一个新方法。此外,这并不能解决代码重复问题,因为我仍然需要多次调用这些方法
3.模板法设计模式
通过在抽象类的方法中添加验证来实现该模式,并定义派生方法将覆盖的新抽象方法
public File GetFile(string Path) {
...Validation
return DoGetFile(Path);
}
protected abstract File DoGetFile(string Path);
这是我找到的最好的方法,但我不喜欢有重复的方法名(除了Do后缀)和描述
4.使抽象方法虚拟化
使方法虚拟化,并在抽象类中实现验证逻辑。派生类需要首先调用基方法,然后执行它们自己的逻辑
public abstract class FileClient {
public virtual File GetFile(string Path) {
...Validation
return null;
}
}
public class FtpClient : FileClient {
public override File GetFile(string Path) {
File file = base.GetFile(Path);
if (file != null) {
return file;
}
...Logic
}
}
这种方法非常干净,但我不喜欢它,原因如下:
第五种方法是使用 使用代码契约,您可以使用接口契约来实现,在编译期间(实际上使用编译后过程),整个契约将自动注入到整个接口的所有实现中 您只需要定义一个
IFileClient
接口和一个合同类。这可能是最优雅、最强大的解决方案
请参阅以下代码示例:
[ContractClass(typeof(IFileClientContract))]
public interface IFileClient
{
File GetFile(string path);
Task<File> GetFileAsync(string path);
void MoveFile(string source, string destination);
}
[ContractClassFor(typeof(IFileClient))]
public abstract class IFileClientContract : IFileClient
{
public File GetFile(string Path)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
throw new NotImplementedException();
}
public Task<File> GetFileAsync(string path)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
throw new NotImplementedException();
}
public void MoveFile(string source, string destination)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(source));
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(destination));
throw new NotImplementedException();
}
}
// Any implementation of IFileClient will need to fulfill
// its contracts, including derived classes of FileClient!
public abstract class FileClient : IFileClient
{
public abstract File GetFile(string Path);
public abstract Task<File> GetFileAsync(string Path);
public abstract void MoveFile(string Source, string Destination);
}
[合同类别(类型(IFileClient合同))]
公共接口IFileClient
{
文件GetFile(字符串路径);
任务GetFileAsync(字符串路径);
void MoveFile(字符串源、字符串目标);
}
[合同类别(类型(IFileClient))]
公共抽象类IFileClient合同:IFileClient
{
公共文件GetFile(字符串路径)
{
Contract.Requires(!string.IsNullOrEmpty(path));
抛出新的NotImplementedException();
}
公共任务GetFileAsync(字符串路径)
{
Contract.Requires(!string.IsNullOrEmpty(path));
抛出新的NotImplementedException();
}
公共无效移动文件(字符串源、字符串目标)
{
Contract.Requires(!string.IsNullOrEmpty(source));
Contract.Requires(!string.IsNullOrEmpty(destination));
抛出新的NotImplementedException();
}
}
//IFileClient的任何实现都需要满足以下条件
//它的契约,包括FileClient的派生类!
公共抽象类FileClient:IFileClient
{
公共抽象文件GetFile(字符串路径);
公共抽象任务GetFileAsync(字符串路径);
公共抽象文件(字符串源、字符串目标);
}
4号滑坡造成的3号滑坡最严重
[ContractClass(typeof(IFileClientContract))]
public interface IFileClient
{
File GetFile(string path);
Task<File> GetFileAsync(string path);
void MoveFile(string source, string destination);
}
[ContractClassFor(typeof(IFileClient))]
public abstract class IFileClientContract : IFileClient
{
public File GetFile(string Path)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
throw new NotImplementedException();
}
public Task<File> GetFileAsync(string path)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(path));
throw new NotImplementedException();
}
public void MoveFile(string source, string destination)
{
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(source));
Contract.Requires<ArgumentNullException>(!string.IsNullOrEmpty(destination));
throw new NotImplementedException();
}
}
// Any implementation of IFileClient will need to fulfill
// its contracts, including derived classes of FileClient!
public abstract class FileClient : IFileClient
{
public abstract File GetFile(string Path);
public abstract Task<File> GetFileAsync(string Path);
public abstract void MoveFile(string Source, string Destination);
}