I have two almost identical c# functions. Because they're so similar I thought I'd try out generics, but I'm stumped on how to do it. Any suggestions, or am I barking up the wrong tree entirely?
public IList<UnitTemplate> UnitTemplates { get; set; }
public IList<QualTemplate> QualTemplates { get; set; }
public QualTemplate FindQualTemplate(string templateID)
{
QualTemplate selectedQualTemplate;
if (QualTemplates.Count == 0)
throw new CreatioException("This user's brand has no QualTemplates. There must be at least one available.");
if (QualTemplates.Count == 1 || String.IsNullOrEmpty(templateID))
selectedQualTemplate = QualTemplates.First();
else
selectedQualTemplate = QualTemplates.Single(x => x.QualTemplateID.ToLower() == templateID.ToLower());
if (selectedQualTemplate == null)
throw new CreatioException(String.Format("No QualTemplate with the id {0} could be found for this user's brand.", templateID));
return selectedQualTemplate;
}
public UnitTemplate FindUnitTemplates(string templateID)
{
UnitTemplate selectedTemplate;
if (UnitTemplates.Count == 0)
throw new CreatioException("This user's brand has no UnitTemplates. There must be at least one available.");
if (UnitTemplates.Count == 1 || String.IsNullOrEmpty(templateID))
selectedTemplate = UnitTemplates.First();
else
selectedTemplate = UnitTemplates.Single(x => x.UnitTemplateID.ToLower() == templateID.ToLower());
if (selectedTemplate == null)
throw new CreatioException(String.Format("No UnitTemplate with the id {0} could be found for this user's brand.", templateID));
return selectedTemplate;
}
The problem you have is that both methods use a property which the two types don’t have in common: QualTemplateID
and UnitTemplateID
. If you can make the following changes to the code structure:
Declare UnitTemplate
and QualTemplate
to derive from a common base type, Template
In that base type, declare a property TemplateID
Get rid of QualTemplateID
and UnitTemplateID
and use the inherited TemplateID
property instead
then you can write the method generically:
public TTemplate FindTemplates<TTemplate>(
IList<TTemplate> templates, string templateID)
where TTemplate : Template
{
TTemplate selectedTemplate;
if (templates.Count == 0)
throw new CreatioException("This user's brand has no template. There must be at least one available.");
if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
selectedTemplate = templates.First();
else
selectedTemplate = templates.Single(x => x.TemplateID.ToLower() == templateID.ToLower());
return selectedTemplate;
}
I’ve removed the if (selectedTemplate == null)
because it would never fire anyway (unless the list is likely to contain nulls, but then the predicate you pass to Single
would crash...).
The above works equally well if you make it an interface instead of a base type.
If you cannot make the changes to the code that I described, then your only option is to pass (as a parameter) a delegate that retrieves the ID:
public TTemplate FindTemplates<TTemplate>(
IList<TTemplate> templates, string templateID,
Func<TTemplate, string> templateIdGetter)
{
TTemplate selectedTemplate;
if (templates.Count == 0)
throw new CreatioException("This user's brand has no template. There must be at least one available.");
if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
selectedTemplate = templates.First();
else
selectedTemplate = templates.Single(x => templateIdGetter(x).ToLower() == templateID.ToLower());
return selectedTemplate;
}
var qTempl = FindTemplates(QualTemplates, "myTemplateId", q => q.QualTemplateID);
var uTempl = FindTemplates(UnitTemplates, "myTemplateId", u => u.UnitTemplateID);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With