I have two methods:
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(); }}
and the second:
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(); }}
As marked with the comment in the code, the validations are the same in both methods. In both methods there is a small part of code which isn't the same.Also the return type is different in both methods.
I am trying to refactor the validations inside the methods into one seperate method.
Here is my attempt:
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."); } }
And here is the call inside 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(); }}
And here is the call inside 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(); } }
There are multiple problems with my attempt:
GetRelatedObjects
andGetRelatedObject
have different return types and my refactored method can only support one- Some of the out variables are not used
GetRelatedObject
but are usedGetRelatedObjects
and reversed
What would be the needed changes to improve my solution so I can get rid of my problems?