我有一个工厂类和CreateInstance方法
CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)
工厂可以根据tipoParametroEntita.TipoCampo.IdTipoCampo
要点是CreateInstance
的第二个参数(parametroEntitaMultiValoreDataSourceProvider
)仅用于创建TipoEntitaTipoParametroEntitaMultiValore
的实例
而不是用于创建TipoEntitaTipoParametroEntitaSingoloValore
public class TipoEntitaTipoParametroEntitaFactory : ITipoEntitaTipoParametroEntitaFactory
{
/// <summary>
/// Creates an instance of TipoEntitaTipoParametroEntitaSingoloValore or TipoEntitaTipoParametroEntitaMultiValore
/// </summary>
public TipoEntitaTipoParametroEntita CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)
{
if (tipoParametroEntita.TipoCampo.IdTipoCampo == (int)EntityModel.Enum.TipoCampo.CampoLibero ||
tipoParametroEntita.TipoCampo.IdTipoCampo == (int)EntityModel.Enum.TipoCampo.CampoLiberoMultiLinea)
{
return new TipoEntitaTipoParametroEntitaSingoloValore(tipoParametroEntita);
}
if (tipoParametroEntita.TipoCampo.IdTipoCampo ==
(int)EntityModel.Enum.TipoCampo.DropdownListQueryDataSource ||
tipoParametroEntita.TipoCampo.IdTipoCampo ==
(int)EntityModel.Enum.TipoCampo.DropdownListTableDataSource)
{
return new TipoEntitaTipoParametroEntitaMultiValore(tipoParametroEntita,
parametroEntitaMultiValoreDataSourceProvider);
}
return null;
}
}
我对这种采用的模式表示怀疑,因为我总是需要传递一个IParametroEntitaMultiValoreDataSourceProvider
的实例,即使它不是必需的,而且读取方法签名的人可能会认为创建任何类型TipoEntitaTipoParametroEntita
需要IParametroEntitaMultiValoreDataSourceProvider
的实例。
什么是更好的方法?两个不同的工厂?只有一个工厂和两个CreateInstance(一个返回TipoEntitaTipoParametroEntitaSingoloValore
而另一个TipoEntitaTipoParametroEntitaMultiValore
)?
我在两种情况下都应该知道哪个工厂或哪个CreateInstance要调用,所以我应该每次都检查tipoParametroEntita.TipoCampo.IdTipoCampo
。但是我想把这个逻辑保留在一个地方。
答案 0 :(得分:2)
从功能编程的角度来看,我在处理所谓的“代数数据类型”(即不同的子类型)时会使用查看访问者模式。无论如何,我并不总是喜欢这种方法,因为它在开始时可能很难。
因此,我只给出基本的想法,以便您可以快速决定是否感兴趣。另请注意,此处的目标是编写带有函数签名的代码,以便在 compile 时将错误发现,与 runtime 相反。
现在简而言之,通过利用C#语言类型检查功能,实现此目的的经典方法是定义一个新访问者,包括具有签名的CreateInstance
的所有不同覆盖:
public IEntitaTipoParametroEntita CreateInstance(SubType1 subType1)
{
// ...
}
public IEntitaTipoParametroEntita CreateInstance(SubType2 subType2)
{
// ...
}
其中每个子类型都应该有自己的
IEntitaTipoParametroEntita accept(CreateVisitor visitor)
{
visitor.CreateInstance(this);
}
这样您就可以避免if
和switch
以及类似的容易出错的子类型检查语法,只需实例化特定的访问者,然后将其传递给任何要处理的子类型。
如果子类型之间存在显着的共性,那么将子类型拆分为单独的物理表可能没什么价值。
因此,就数据库设计而言,“ table per hierarchy ”(利用类型鉴别器列来保存类型信息)似乎更适合您的示例:它通过非规范化来实现多态性SQL架构。要指示Entity Framework使用此策略,所需的只是从DbContext
类派生一个类,并为超类型添加DBSet
属性,同时不添加DBSet
属性亚型。