我有两个几乎相同的c#函数。因为它们非常相似,所以我认为我会尝试使用仿制药,但我很难理解如何做到这一点。任何建议,还是我完全咆哮错误的树?
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;
}
答案 0 :(得分:8)
您遇到的问题是两种方法都使用两种类型没有共同点的属性:QualTemplateID
和UnitTemplateID
。如果您可以对代码结构进行以下更改:
声明UnitTemplate
和QualTemplate
派生自公共基本类型Template
在该基本类型中,声明属性TemplateID
摆脱QualTemplateID
和UnitTemplateID
并使用继承的TemplateID
属性
然后你可以编写一般的方法:
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;
}
我删除了if (selectedTemplate == null)
因为它永远不会触发(除非列表可能包含空值,但是传递给Single
的谓词会崩溃...)。
如果你把它变成一个界面而不是一个基本类型,上面的效果同样很好。
如果您无法对我描述的代码进行更改,那么您唯一的选择是传递(作为参数)检索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);
答案 1 :(得分:6)
我会使用一个界面,例如:
public interface ITemplate
{
string TemplateId { get; }
}
明确实施:
public class UnitTemplate : ITemplate {
public string UnitTemplateID { get; set; }
string ITemplate.TemplateId { get { return UnitTemplateID; } }
}
public class QualTemplate : ITemplate
{
public string QualTemplateID { get; set; }
string ITemplate.TemplateId { get { return QualTemplateID; } }
}
然后我可以编写一个通用扩展方法来处理任何T
:
public static class TemplateExtensions
{
public static T Find<T>(this ICollection<T> templates, string templateID) where T : ITemplate
{
T selectedTemplate;
if (templates.Count == 0)
throw new CreatioException("This user's brand has no templates. 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());
if (selectedTemplate == null)
throw new CreatioException(String.Format("No template with the id {0} could be found for this user's brand.", templateID));
return selectedTemplate;
}
}
最后,代理这些方法:
public QualTemplate FindQualTemplate(string templateID)
{
return QualTemplates.Find(templateID);
}
public UnitTemplate FindUnitTemplates(string templateID)
{
return UnitTemplates.Find(templateID);
}
如果您想避开界面,可以改用选择器:
public QualTemplate FindQualTemplate(string templateID)
{
return Find(QualTemplates, templateID, x => x.QualTemplateID);
}
public UnitTemplate FindUnitTemplates(string templateID)
{
return Find(UnitTemplates, templateID, x => x.UnitTemplateID);
}
static T Find<T>(ICollection<T> templates, string templateID, Func<T, string> selector)
{
T selectedTemplate;
if (templates.Count == 0)
throw new CreatioException("This user's brand has no templates. There must be at least one available.");
if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
selectedTemplate = templates.First();
else
selectedTemplate = templates.Single(x => selector(x).ToLower() == templateID.ToLower());
if (selectedTemplate == null)
throw new CreatioException(String.Format("No template with the id {0} could be found for this user's brand.", templateID));
return selectedTemplate;
}
答案 2 :(得分:3)
您可以使用Func:
public IList<UnitTemplate> UnitTemplates { get; set; }
public IList<QualTemplate> QualTemplates { get; set; }
public QualTemplate FindQualTemplate(string templateID)
{
return FindTemplatesImpl(templateID, x => x.QualTemplateID, QualTemplates );
}
public UnitTemplate FindUnitTemplates(string templateID)
{
return FindTemplatesImpl(templateID, x => x.UnitTemplateID, UnitTemplates );
}
public T FindTemplatesImpl<T>(string templateID, Func<T, string> expr, IList<T> templates)
{
T selectedTemplate;
if (templates.Count == 0)
throw new CreatioException("This user's brand has no Templates. There must be at least one available.");
if (templates.Count == 1 || String.IsNullOrEmpty(templateID))
selectedTemplate = templates.First();
else
selectedTemplate = templates.Single(x => expr(x).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;
}
答案 3 :(得分:1)
这不容易实现。 UnitTemplates和QualTemplates需要实现相同的接口,或者具有暴露您正在使用的成员的相同基类,QualTemplate和UnitTemplate也是如此。即便如此,您还需要将工厂传递给方法(例如UnitTemplates作为参数),并且您需要在外部的单个调用中指定您使用的谓词(因为ID属性名称不同)。
答案 4 :(得分:0)
这是我能看到的最简单的解决方案,如果你愿意,你甚至可以将其作为扩展方法。 (如果你不只是删除静电和这件)
public static class Extension {
public static T FindTemplates<T>(this IList<T> list, string templateID, Func<string,T> selector)
{
T selectedTemplate;
if (list.Count == 0){
throw new CreationException("This user's brand has no UnitTemplates. There must be at least one available.");
}
if (list.Count == 1 || String.IsNullOrEmpty(templateID)){
selectedTemplate = list.First();
}
else{
selectedTemplate = selector(templateID);
}
if (selectedTemplate == null){
throw new CreationException(String.Format("No UnitTemplate with the id {0} could be found for this user's brand.", templateID));
}
return selectedTemplate;
}
}
然后使用就像这样:
IList<UnitTemplate> test = new List<UnitTemplate>();
UnitTemplate t = test.FindTemplates("id", (string x) => test.Single(y => y.UnitTemplateID.ToLower() == x.ToLower()));