C# 控制器动作法中的开闭原理
我有一个ASP.NETMVC项目,我需要遵循开放-封闭原则 该项目将C# 控制器动作法中的开闭原理,c#,solid-principles,C#,Solid Principles,我有一个ASP.NETMVC项目,我需要遵循开放-封闭原则 该项目将.csv文件从数据库转换为模型,但将来我们可能还必须将excel文件从数据库转换为相同的模型 现在,控制器中有以下代码: public ActionResult Index(HttpPostedFileBase file) { // Verify that the user selected a file if (file != null && file.ContentLength
.csv
文件从数据库转换为模型,但将来我们可能还必须将excel文件从数据库转换为相同的模型
现在,控制器中有以下代码:
public ActionResult Index(HttpPostedFileBase file)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
var path = FileHelper.GetFilePath(file);
string filePath = path.Item1;
if (!string.IsNullOrEmpty(filePath))
{
if (path.Item2 == "." + Enums.FileType.csv.ToString())
{
List<Company> companiesList = Convertor.ConvertCsvToCompanyModel(filePath);
if (companiesList != null && companiesList.Count() > 0)
{
try
{
foreach (var company in companiesList)
{
companyRepository.SaveCompanyItem(company);
}
}
catch(Exception ex)
{
obj.Handle("Something went wrong at save" + ex.Message);
}
}
TempData["Message"] = "The file import was sucessfull!";
}
}
}
TempData["ErrorMessage"] = "Please select file";
// redirect back to the index action to show the form once again
return RedirectToAction("Index");
}
公共操作结果索引(HttpPostedFileBase文件)
{
//验证用户是否选择了一个文件
如果(file!=null&&file.ContentLength>0)
{
var path=FileHelper.GetFilePath(文件);
字符串filePath=path.Item1;
如果(!string.IsNullOrEmpty(文件路径))
{
if(path.Item2==““+Enums.FileType.csv.ToString())
{
列表公司列表=Convertor.ConvertCsvToCompanyModel(文件路径);
if(companiesList!=null&&companiesList.Count()>0)
{
尝试
{
foreach(公司列表中的var公司)
{
companyRepository.SaveCompanyItem(公司);
}
}
捕获(例外情况除外)
{
obj.Handle(“保存时出错”+ex.Message);
}
}
TempData[“Message”]=“文件导入成功!”;
}
}
}
TempData[“ErrorMessage”]=“请选择文件”;
//重定向回索引操作以再次显示表单
返回操作(“索引”);
}
你能给我一些提示如何做到这一点吗?我认为,如果我们想将Excel转换为文件,最好不要在这个操作方法中使用更多的if-s。谢谢 相信我,控制器或甚至
索引
操作与您在文件
上执行的任何操作无关。他们所关心的只是用户上传的文件中的数据
我会将所有文件
内容移动到单独的类中,比如说文件服务
,然后在控制器内使用此服务。由于需要同时支持CSV(当前)、Excel(未来)或两者(您没有提到这一点),我们可以考虑策略模式和工厂方法模式
public interface IFileProcessor {
// add proper constraint for T
List < T > GetRecords < T > (...);
}
public class CsvFileProcessor: IFileProcessor {
List < T > GetRecords < T > (...) {}
}
public class ExcelFileProcessor: IFileProcessor {
List < T > GetRecords < T > (...) {}
}
public class FileService {
public List < T > ReadFile < T > (HttpPostedFileBase file) {
// do whatever with `file` here
IFileProcessor fileProcessor = GetFileProcessor( < fileExt > );
return fileProcessor.GetRecords < T > (...);
}
// This is not exact implementation of factory but it serves the same purpose as factory method.
private static IFileProcessor GetFileProcessor(string fileExt) {
if ( < csv > ) {
return ServiceLocator.Current.GetInstance < IFileProcessor > ("csv");
}
else if ( < excel > ) {
return ServiceLocator.Current.GetInstance < IFileProcessor > ("excel");
}
}
}
公共接口IFileProcessor{
//为T添加适当的约束
列表CsvFileProcessor
和ExcelFileProcessor
可以轻松使用和libs。您只需指定模型/实体类型,libs将返回反序列化为该类型的记录列表
现在将此
文件服务
注入控制器。相信我,控制器甚至索引
操作与您在文件
上执行的任何操作无关。他们所关心的只是用户上传的文件中的数据
我会将所有文件
内容移动到单独的类中,比如说文件服务
,然后在控制器内使用此服务。由于需要同时支持CSV(当前)、Excel(未来)或两者(您没有提到这一点),我们可以考虑策略模式和工厂方法模式
public interface IFileProcessor {
// add proper constraint for T
List < T > GetRecords < T > (...);
}
public class CsvFileProcessor: IFileProcessor {
List < T > GetRecords < T > (...) {}
}
public class ExcelFileProcessor: IFileProcessor {
List < T > GetRecords < T > (...) {}
}
public class FileService {
public List < T > ReadFile < T > (HttpPostedFileBase file) {
// do whatever with `file` here
IFileProcessor fileProcessor = GetFileProcessor( < fileExt > );
return fileProcessor.GetRecords < T > (...);
}
// This is not exact implementation of factory but it serves the same purpose as factory method.
private static IFileProcessor GetFileProcessor(string fileExt) {
if ( < csv > ) {
return ServiceLocator.Current.GetInstance < IFileProcessor > ("csv");
}
else if ( < excel > ) {
return ServiceLocator.Current.GetInstance < IFileProcessor > ("excel");
}
}
}
公共接口IFileProcessor{
//为T添加适当的约束
列表CsvFileProcessor
和ExcelFileProcessor
可以轻松使用和libs。您只需指定模型/实体类型,libs将返回反序列化为该类型的记录列表
现在,将这个
文件服务
注入控制器。这个逻辑应该在服务内部。如果你想谈论OCP,我宁愿看一看名为转换器
的类,它看起来会做很多不相关的事情,更不用说它是静态访问的。您发布的方法的问题更像是SRP冲突:1。验证输入,并据此决定行动和结果。执行操作以处理输入,3。坚持结果。还有2。三,。应该位于上面评论中提到的另一层。看起来像是一个Stra