如何利用泛型来填充派生类模型以避免代码重复



我有两个类似的类型,每个类型都有不同的处理逻辑。基于该处理,我正在准备一个结果,并将其返回给消费者(mvc应用程序、控制台应用程序等)

  • 类型1
  • 类型2

现在的问题是,有些代码在这两种类型中都很常见。唯一不同的部分是两种类型的类(Type1Manager,Type2Manager)其实际上包含用于处理CCD_ 2和准备结果(Type1Model,Type2Model)的逻辑。

public class Variant
{
public int Id { get; set; }
public string Name { get; set; }
public List<Subvariants> Subvariants { get; set; }
}
public class Subvariants
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class BaseManager
{
//Other shared code
public abstract ExecutionResult GetExecutionResult(Variant model);
}
public class ExecutionResult
{
public string Name { get; set; }
public string ErrorMessage { get; set; }
public bool Success { get; set; }
public List<Type1Model> Types1 { get; set; }
public List<Type2Model> Types2 { get; set; }
}
public abstract class BaseModel<T>
{
public string Name { get; set; }
public T Value { get; set; }
public T Coordinates { get; set; }
public decimal OverAllPercentage { get; set; }
}
public class Type1Model : BaseModel<int>
{
public decimal MiscPercentage { get; set; }
public int PerformanceCounter { get; set; }
}
public class Type2Model : BaseModel<decimal> { }
public class Type1 : BaseManager
{
public override ExecutionResult GetExecutionResult(Variant model)
{
var executionResult = new ExecutionResult();
executionResult.Name = model.Name;
var type1Result = new List<Type1Model>();
try
{
for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
{
var left = model.Subvariants[counter];
var right = model.Subvariants[counter + 1];
using (var t = new Type1Manager(model))
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
t.Start(i);
if (counter == 0)
{
type1Result.Add(new Type1Model
{
Name = left.Name,
Value = t.Left
});
}
}
else
{
t.Start(i);
type1Result.Add(new Type1Model
{
Name = right.Name,
Value = t.Right,
Coordinates = t.Left + t.Right,
OverAllPercentage = t.OverAllPercentage,
PerformanceCounter = (t.NetPlus + t.AverageRatio),
MiscPercentage = t.MiscPercentage
});
}
}
}
}
executionResult.Types1 = type1Result;
}
catch (Exception ex)
{
executionResult.Success = false;
executionResult.ErrorMessage = ex.Message;
}
return executionResult;
}
}
internal class Type1Manager : IDisposable
{
private Variant model;
public int Right { get; private set; }
public int Left { get; private set; }
public int NetPlus { get; private set; }
public int AverageRatio { get; private set; }
public decimal OverAllPercentage { get; private set; }
public decimal MiscPercentage { get; private set; }
public Type1Manager(Variant model)
{
this.model = model;
}
public void Start(int i)
{
}
public void Dispose()
{
throw new NotImplementedException();
}
}
public class Type2 : BaseManager
{
public override ExecutionResult GetExecutionResult(Variant model)
{
var executionResult = new ExecutionResult();
executionResult.Name = model.Name;
var type2Result = new List<Type2Model>();
try
{
for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
{
var left = model.Subvariants[counter];
var right = model.Subvariants[counter + 1];
using (var t = new Type2Manager(model))
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
t.Start(i);
if (counter == 0)
{
type2Result.Add(new Type2Model
{
Name = left.Name,
Value = t.Left
});
}
}
else
{
t.Start(i);
type2Result.Add(new Type2Model
{
Name = right.Name,
Value = t.Right,
Coordinates = t.Left + t.Right,
OverAllPercentage = t.OverAllPercentage,
});
}
}
}
}
executionResult.Types2 = type2Result;
}
catch (Exception ex)
{
executionResult.Success = false;
executionResult.ErrorMessage = ex.Message;
}
return executionResult;
}
}
internal class Type2Manager : IDisposable
{
private Variant model;
public decimal Right { get; private set; }
public decimal Left { get; private set; }
public decimal OverAllPercentage { get; private set; }
public Type2Manager(Variant model)
{
this.model = model;
}
public void Start(int i)
{
}
public void Dispose()
{
throw new NotImplementedException();
}
}

我现在面临的问题是Type1 needs Type1ModelType2 needs Type2Model。即使我试图移出BaseManager类中的公共代码,我将如何填充Type1Model and Type2Model模型?我正在努力重构这两种类型的代码,并在基类中移动一些公共逻辑。

是否可以重构出两种类型的重复代码并将其移到基类中?

更新:

public abstract class BaseManager
{
public abstract ExecutionResult GetExecutionResult(Variant model);
public abstract void ExecuteAndSave(Variant model, string connectionString);
}


public class Type1 : BaseManager
{
public override void ExecuteAndSave(Variant model, string connectionString)
{
//other logic
var t = new Type1Manager(new SaveData());
}
public override ExecutionResult GetExecutionResult(Variant model)
{
var executionResult = new ExecutionResult();
executionResult.Name = model.Name;
var type1Result = new List<Type1Model>();
try
{
for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
{
var left = model.Subvariants[counter];
var right = model.Subvariants[counter + 1];
using (var t = new Type1Manager(new Repository()))
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
t.Start(null,null);
if (counter == 0)
{
type1Result.Add(new Type1Model
{
Name = left.Name,
Value = t.Left
});
}
}
else
{
t.Start(null,null);
type1Result.Add(new Type1Model
{
Name = right.Name,
Value = t.Right,
Coordinates = t.Left + t.Right,
OverAllPercentage = t.OverAllPercentage,
PerformanceCounter = (t.NetPlus + t.AverageRatio),
MiscPercentage = t.MiscPercentage
});
}
}
}
}
executionResult.Types1 = type1Result;
}
catch (Exception ex)
{
executionResult.Success = false;
executionResult.ErrorMessage = ex.Message;
}
return executionResult;
}
}
internal class Type1Manager : IDisposable
{
public int Right { get; private set; }
public int Left { get; private set; }
public int NetPlus { get; private set; }
public int AverageRatio { get; private set; }
public decimal OverAllPercentage { get; private set; }
public decimal MiscPercentage { get; private set; }
private Repository _repository;
public Type1Manager(Repository repository)
{
this._repository = repository;
}
public void Start(string connectionString,string sqlQuery)
{
}
public void Dispose()
{
throw new NotImplementedException();
}
}
public class Repository
{
//Dont save result here.Used only for Type1
}
public class SaveData : Repository
{
//Save result here.Used only for Type1
}
public class Type2 : BaseManager
{
public override void ExecuteAndSave(Variant model, string connectionString)
{
//using (var t = new Type2Manager(2)//not hardcoded.taken from model
//Save data here returns from Type2Manager instance
}
public override ExecutionResult GetExecutionResult(Variant model)
{
var executionResult = new ExecutionResult();
executionResult.Name = model.Name;
var type2Result = new List<Type2Model>();
try
{
for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
{
var left = model.Subvariants[counter];
var right = model.Subvariants[counter + 1];
using (var t = new Type2Manager(2)) //not hardcoded.taken from model
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
t.Start(null,null);
if (counter == 0)
{
type2Result.Add(new Type2Model
{
Name = left.Name,
Value = t.Left
});
}
}
else
{
t.Start(null,null);
type2Result.Add(new Type2Model
{
Name = right.Name,
Value = t.Right,
Coordinates = t.Left + t.Right,
OverAllPercentage = t.OverAllPercentage,
});
}
}
}
}
executionResult.Types2 = type2Result;
}
catch (Exception ex)
{
executionResult.Success = false;
executionResult.ErrorMessage = ex.Message;
}
return executionResult;
}
}
internal class Type2Manager : IDisposable
{
public decimal Right { get; private set; }
public decimal Left { get; private set; }
public decimal OverAllPercentage { get; private set; }
int precision;
public Type2Manager(int precision)
{
this.precision = precision;
}
public void Start(string connectionString, string sqlQuery)
{
}
public void Dispose()
{
throw new NotImplementedException();
}
}
  • 变体:区域
  • 子变体:子区域
  • 类型1:分析计算器
  • 类型2:聚合计算器

如果使基类成为泛型并设置正确的约束,则可以将大部分代码拉到基类中。此外,您需要为每种类型创建一个特定的实现
下面的样品应该会给你一个想法:

public abstract class SharedLogicClass<TValue, TType>
where TType : BaseModel<TValue>, new
{
public override ExecutionResult GetExecutionResult(Variant model)
{
var executionResult = new ExecutionResult();
executionResult.Name = model.Name;
var type1Result = new List<TTYpe>();
try
{
for (int counter = 0; counter < model.Subvariants.Count - 1; counter++) 
{
var left = model.Subvariants.Count[counter];
var right = model.Subvariants.Count[counter + 1];
using (var t = CreateTypeManager(model))
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
t.Start(i);
if (counter == 0)
{
type1Result.Add(new TType()
{
Name = left.Name,
Value = t.LeftValue
});
}
}
else
{
t.Start(i);
var type = new TType()
{
Name = right.Name,
Value = t.RightValue,
Coordinates = t.Left + t.Right,
OverAllPercentage = t.OverAllPercentage,
});
AssignAdditionalValues(type, t);
type1Result.Add(type);
}
}
}
}
AssignExecutionResult(executionResult, type1Result);
}
catch (Exception ex)
{
executionResult.Success = false;
executionResult.ErrorMessage = ex.Message;
}
return executionResult;
}
protected abstract BaseManager CreateTypeManager(Variant model);
protected virtual void AssignAdditionalData(Type1Model type, TypeManager t) {}
protected abstract void AssignExecutionResultList(ExecutionResult res, IList<TType> lst);
}
public class SharedLogicImplementationType1 : SharedLogicClass<int, Type1Model>
{
protected override BaseManager CreateTypeManager(Variant model)
{
return new Type1Manager(model);
}
protected override void AssignAdditionalData(Type1Model type, TypeManager t)
{
type.PerformanceCounter = (t.NetPlus + t.AverageRatio);
type.MiscPercentage = t.MiscPercentage;
}
protected override void AssignExecutionResultList(ExecutionResult res, IList<Type1Model> lst)
{
res.Types1 = lst;
}
}

public class SharedLogicImplementationType2 : SharedLogicClass<decimal, Type2Model>
{
protected override BaseManager CreateTypeManager(Variant model)
{
return new Type2Manager(model);
}
protected override void AssignExecutionResultList(ExecutionResult res, IList<Type2Model> lst)
{
res.Types2 = lst;
}
}

请将代码视为示例,而不是成品。

您的对象模型真的太夸张了。我已经设法消除了大部分重复,但对于类名,很难建议进行任何进一步的重构。我怀疑你这样做很难。

这是我得到的:

public class Variant
{
public int Id { get; set; }
public string Name { get; set; }
public List<Subvariants> Subvariants { get; set; }
}
public class Subvariants
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ExecutionResult<T, TModel>
where TModel : BaseModel<T>
{
public string Name { get; set; }
public string ErrorMessage { get; set; }
public bool Success { get; set; }
public List<TModel> Types { get; set; }
}
public abstract class BaseModel<T>
{
public string Name { get; set; }
public T Value { get; set; }
public T Coordinates { get; set; }
public decimal OverAllPercentage { get; set; }
}
public class Type1Model : BaseModel<int>
{
public decimal MiscPercentage { get; set; }
public int PerformanceCounter { get; set; }
}
public class Type2Model : BaseModel<decimal> { }
public abstract class BaseManager<T, TManager, TModel, R>
where TManager : TypeBaseManager<T>
where TModel : BaseModel<T>
where R : ExecutionResult<T, TModel>, new()
{
protected abstract TManager CreateTypeManager(Variant model);
protected abstract TModel CreateTypeModelLeft(TManager typeManager, Subvariants subvariant);
protected abstract TModel CreateTypeModelRight(TManager typeManager, Subvariants subvariant);
public R GetExecutionResult(Variant model)
{
var executionResult = new R();
executionResult.Name = model.Name;
var type1Result = new List<TModel>();
try
{
for (int counter = 0; counter < model.Subvariants.Count - 1; counter++)
{
var left = model.Subvariants[counter];
var right = model.Subvariants[counter + 1];
using (var t = CreateTypeManager(model))
{
for (int i = 0; i < 2; i++)
{
if (i == 0)
{
t.Start(i);
if (counter == 0)
{
type1Result.Add(CreateTypeModelLeft(t, left));
}
}
else
{
t.Start(i);
type1Result.Add(CreateTypeModelRight(t, right));
}
}
}
}
executionResult.Types = type1Result;
}
catch (Exception ex)
{
executionResult.Success = false;
executionResult.ErrorMessage = ex.Message;
}
return executionResult;
}
}
public class Type1 : BaseManager<int, Type1Manager, Type1Model, ExecutionResult<int, Type1Model>>
{
protected override Type1Manager CreateTypeManager(Variant model)
{
return new Type1Manager(model);
}
protected override Type1Model CreateTypeModelLeft(Type1Manager typeManager, Subvariants subvariant)
{
return new Type1Model
{
Name = subvariant.Name,
Value = typeManager.Left
};
}
protected override Type1Model CreateTypeModelRight(Type1Manager typeManager, Subvariants subvariant)
{
return new Type1Model
{
Name = subvariant.Name,
Value = typeManager.Right,
Coordinates = typeManager.Left + typeManager.Right,
OverAllPercentage = typeManager.OverAllPercentage,
PerformanceCounter = (typeManager.NetPlus + typeManager.AverageRatio),
MiscPercentage = typeManager.MiscPercentage
};
}
}
public class Type2 : BaseManager<decimal, Type2Manager, Type2Model, ExecutionResult<decimal, Type2Model>>
{
protected override Type2Manager CreateTypeManager(Variant model)
{
return new Type2Manager(model);
}
protected override Type2Model CreateTypeModelLeft(Type2Manager typeManager, Subvariants subvariant)
{
return new Type2Model { Name = subvariant.Name, Value = typeManager.Left };
}
protected override Type2Model CreateTypeModelRight(Type2Manager typeManager, Subvariants subvariant)
{
return new Type2Model
{
Name = subvariant.Name,
Value = typeManager.Right,
Coordinates = typeManager.Left + typeManager.Right,
OverAllPercentage = typeManager.OverAllPercentage,
};
}
}
public class TypeBaseManager<T> : IDisposable
{
protected Variant model;
public T Right { get; private set; }
public T Left { get; private set; }
public decimal OverAllPercentage { get; private set; }
public TypeBaseManager(Variant model)
{
this.model = model;
}
public void Start(int i)
{
}
public void Dispose()
{
throw new NotImplementedException();
}
}
public class Type1Manager : TypeBaseManager<int>
{
public int NetPlus { get; private set; }
public int AverageRatio { get; private set; }
public decimal MiscPercentage { get; private set; }
public Type1Manager(Variant model) : base(model) { }
}
public class Type2Manager : TypeBaseManager<decimal>
{
public Type2Manager(Variant model) : base(model) { }
}

我非常希望看到您以某种一致性重命名类。

此外,我希望看到catch (Exception ex)被删除——看起来你的代码不会在那里失败,如果可以的话,看起来你可以在不诉诸异常处理的情况下围绕失败进行编码。毕竟,异常处理应该用于处理异常情况,如硬盘空间不足。