c# - 重构类似的方法,但具有不同的返回类型
问题描述
我有两种方法:
public ActionResult<IEnumerable<IDataObject>> GetRelatedObjects([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName)
{
if (string.IsNullOrWhiteSpace(primaryKey))
{
return BadRequest("Primary key cannot be empty.");
}
if (!TryGetClass(className, out var metaClass))
{
return NotFound($"Class [{className}] does not exist.");
}
if (!metaClass.Properties.TryGetValue(relationName, out var property))
{
return NotFound($"Class [{metaClass}] does not contain property [{relationName}].");
}
if (!(property is IMetaRelation relation))
{
return BadRequest($"Property [{relationName}] is not a relation.");
}
if (relation.Target.Cardinality != MetaCardinality.Multiple)
{
return BadRequest(`$"Relation [{relationName}] has multiple cardinality."`);
}
if (!_primaryKeyHandler.TryParsePrimaryKey(metaClass, primaryKey, out var primaryKeyValues))
{
return BadRequest("Cannot convert the primaryKey to the correct type.");
}
if (!_dataCalculator.SupportsData(metaClass))
{
return BadRequest($"The class [{className}] is not persisted");
}
var metaObject = _dataAccess.GetObject<IDataObject>(DataSession, metaClass, primaryKeyValues);
if (metaObject == null)
{
return NotFound($"The metaObject for the primaryKey [{primaryKey}] nad the class [{className}] cannot be empty.");
}
// The validations above are the same as for GetRelatedObject()
try
{
var list = _dataAccess.GetRelatedList<IDataObject>(DataSession, metaClass, primaryKeyValues, relation);
return new ActionResult<IEnumerable<IDataObject>>(list);
}
catch (InvalidAuthorizationException)
{
return Unauthorized();
}
}
第二个:
public ActionResult<IDataObject> GetRelatedObject([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName)
{
if (string.IsNullOrWhiteSpace(primaryKey))
{
return BadRequest("Primary key cannot be empty.");
}
if (!TryGetClass(className, out var metaClass))
{
return NotFound($"Class [{className}] does not exist.");
}
if (!metaClass.Properties.TryGetValue(relationName, out var property))
{
return NotFound($"Class [{metaClass}] does not contain property [{relationName}].");
}
if (!(property is IMetaRelation relation))
{
return BadRequest($"Property [{relationName}] is not a relation.");
}
if (relation.Target.Cardinality == MetaCardinality.Multiple)
{
return BadRequest($"Relation [{relationName}] has multiple cardinality.");
}
if (!_primaryKeyHandler.TryParsePrimaryKey(metaClass, primaryKey, out var primaryKeyValues))
{
return BadRequest("Cannot convert the primaryKey to the correct type.");
}
if (!_dataCalculator.SupportsData(metaClass))
{
return BadRequest($"The class [{className}] is not persisted");
}
var metaObject = _dataAccess.GetObject<IDataObject>(DataSession, metaClass, primaryKeyValues);
if (metaObject == null)
{
return NotFound($"The metaObject for the primaryKey [{primaryKey}] nad the class [{className}] cannot be empty.");
}
// The validations above are the same as for GetRelatedObjects()
try
{
var relationValue = metaObject.GetObject<IDataObject>(relation);
return new ActionResult<IDataObject>(relationValue);
}
catch (InvalidAuthorizationException)
{
return Unauthorized();
}
}
正如代码中的注释所标记的那样,两种方法的验证都是相同的。在这两种方法中,都有一小部分代码不一样。两种方法的返回类型也不同。
我正在尝试将方法内部的验证重构为一个单独的方法。
这是我的尝试:
private void RelatedObject(string className, string primaryKey, string relationName, out IMetaRelation metaRelation, out IDataObject metaObject, out ActionResult<IDataObject> actionResult, out IDictionary<IMetaProperty, object> primaryKeyValues, out IMetaClass metaClass)
{
actionResult = null;
metaRelation = null;
if (string.IsNullOrWhiteSpace(primaryKey))
{
actionResult = BadRequest("Primary key cannot be empty.");
}
if (!TryGetClass(className, out metaClass))
{
actionResult = NotFound($"Class [{className}] does not exist.");
}
if (!metaClass.Properties.TryGetValue(relationName, out var property))
{
actionResult = NotFound($"Class [{metaClass}] does not contain property [{relationName}].");
}
if (!(property is IMetaRelation relation))
{
actionResult = BadRequest($"Property [{relationName}] is not a relation.");
}
if (relation.Target.Cardinality == MetaCardinality.Multiple)
{
actionResult = BadRequest($"Relation [{relationName}] has multiple cardinality.");
}
if (!_primaryKeyHandler.TryParsePrimaryKey(metaClass, primaryKey, out primaryKeyValues))
{
actionResult = BadRequest("Cannot convert the primaryKey to the correct type.");
}
if (!_dataCalculator.SupportsData(metaClass))
{
actionResult = BadRequest($"The class [{className}] is not persisted");
}
metaObject = _dataAccess.GetObject<IDataObject>(DataSession, metaClass, primaryKeyValues);
if (metaObject == null)
{
actionResult = NotFound($"The metaObject for the primaryKey [{primaryKey}] nad the class [{className}] cannot be empty.");
}
}
这是 GetRelatedObject 内部的调用:
public ActionResult<IDataObject> GetRelatedObject([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName)
{
RelatedObject(className, primaryKey, relationName, out var relation, out var metaObject, out var actionResult, out var primaryKeyValues, out var metaClass);
if (actionResult != null)
{
return actionResult;
}
try
{
var relationValue = metaObject.GetObject<IDataObject>(relation);
return new ActionResult<IDataObject>(relationValue);
}
catch (InvalidAuthorizationException)
{
return Unauthorized();
}
}
这是 GetRelatedObjects 内部的调用:
public ActionResult<IEnumerable<IDataObject>> GetRelatedObjects([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName)
{
RelatedObject(className, primaryKey, relationName, out var relation, out var metaObject, out var actionResult, out var primaryKeyValues, out var metaClass);
if (actionResult != null)
{
return actionResult;
}
try
{
var list = _dataAccess.GetRelatedList<IDataObject>(DataSession, metaClass, primaryKeyValues, relation);
return new ActionResult<IEnumerable<IDataObject>>(list);
}
catch (InvalidAuthorizationException)
{
return Unauthorized();
}
}
我的尝试存在多个问题:
- GetRelatedObjects 和 GetRelatedObject 有不同的返回类型,我重构的方法只能支持一种
- 一些out变量没有使用GetRelatedObject而是使用GetRelatedObjects并反转
需要哪些更改来改进我的解决方案以便我可以摆脱我的问题?
解决方案
您已经在代码中声明每种方法的验证都是相同的......但它们不是。
从 GetRelatedObject:
if (relation.Target.Cardinality == MetaCardinality.Multiple)
{
return BadRequest($"Relation [{relationName}] has multiple cardinality.");
}
来自 GetRelatedObjects:
if (relation.Target.Cardinality != MetaCardinality.Multiple)
{
return BadRequest("The cardinality is not multiple");
}
话虽如此,我会做这样的事情并将验证合并到一个方法中以减少代码重复,添加一个参数以在多个/单个基数之间切换。
未经测试,所以我不知道它是否真的有效;)
public ActionResult<IDataObject> GetRelatedObject([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName)
{
var validationError = ValidateRequest(className, primaryKey, relationName, allowMultipleCardinality: false);
if (validationError) return validationError;
try
{
var relationValue = metaObject.GetObject<IDataObject>(relation);
return new ActionResult<IDataObject>(relationValue);
}
catch (InvalidAuthorizationException)
{
return Unauthorized();
}
}
public ActionResult<IEnumerable<IDataObject>> GetRelatedObjects([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName)
{
var validationError = ValidateRequest(className, primaryKey, relationName, allowMultipleCardinality: true);
if (validationError) return validationError;
try
{
var list = _dataAccess.GetRelatedList<IDataObject>(DataSession, metaClass, primaryKeyValues, relation);
return new ActionResult<IEnumerable<IDataObject>>(list);
}
catch (InvalidAuthorizationException)
{
return Unauthorized();
}
}
private ActionResult ValidateRequest([CanBeNull] string className, [CanBeNull] string primaryKey, [CanBeNull] string relationName, bool allowMultipleCardinality)
{
if (string.IsNullOrWhiteSpace(primaryKey))
{
return BadRequest("Primary key cannot be empty.");
}
if (!TryGetClass(className, out var metaClass))
{
return NotFound($"Class [{className}] does not exist.");
}
if (!metaClass.Properties.TryGetValue(relationName, out var property))
{
return NotFound($"Class [{metaClass}] does not contain property [{relationName}].");
}
if (!(property is IMetaRelation relation))
{
return BadRequest($"Property [{relationName}] is not a relation.");
}
if (AllowMultipleCardinality)
{
if (relation.Target.Cardinality != MetaCardinality.Multiple)
{
return BadRequest("The cardinality is not multiple");
}
}
else
{
if (relation.Target.Cardinality == MetaCardinality.Multiple)
{
return BadRequest($"Relation [{relationName}] has multiple cardinality.");
}
}
if (!_primaryKeyHandler.TryParsePrimaryKey(metaClass, primaryKey, out var primaryKeyValues))
{
return BadRequest("Cannot convert the primaryKey to the correct type.");
}
if (!_dataCalculator.SupportsData(metaClass))
{
return BadRequest($"The class [{className}] is not persisted");
}
var metaObject = _dataAccess.GetObject<IDataObject>(DataSession, metaClass, primaryKeyValues);
if (metaObject == null)
{
return NotFound($"The metaObject for the primaryKey [{primaryKey}] nad the class [{className}] cannot be empty.");
}
}
推荐阅读
- android - gradle 未解决的依赖
- python - Pytorch 中的批量矩阵乘法 - 对输出维度的处理感到困惑
- c# - 更改数据库架构和实体时单元测试失败,但单元测试未更改
- c# - MS Graph 循环遍历 IListItemsCollectionPage 中的每个项目
- javascript - 为焦点上的jquery可拖动元素添加边框
- r - 如何在 geom_density 上指定两条具有不同颜色和形状的曲线
- java - 有什么方法可以加密外部 SD 卡上的 SQLite 数据库?
- c# - 向 AD 查询 LAPS ExpirationTime 时返回 System.__ComObject
- python-3.x - Scrapyd 不会将包含 selenium 模块的蜘蛛项目部署到我的本地主机
- android - Bindable 必须在 Observable 类的成员上