特定子类型不需要工厂 CreateInstance 参数方法
Factory CreateInstance argument method not necessary for a specific subtype
我有一个工厂 class 和 CreateInstance 方法
CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)
工厂可以根据 tipoParametroEntita.TipoCampo.IdTipoCampo
的值实例化两个不同的子类型
重点是 CreateInstance
(parametroEntitaMultiValoreDataSourceProvider
) 的第二个参数仅用于创建 TipoEntitaTipoParametroEntitaMultiValore
的实例
while 不用于创建 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
。但我只想把这个逻辑放在一个地方。
从函数式编程的角度来看,在处理所谓的 "algebraic data types" 即不同的子类型时,我习惯于查看访问者模式。无论如何,我并不总是喜欢这种方法,因为一开始它可能很困难。
因此我只给出基本思路,以便您可以快速决定是否感兴趣。另请注意,此处的目标是编写具有函数签名的代码,以便可以在 compile 时间发现错误,与 runtime 相反。 =22=]
简而言之,class通过利用 C# 语言类型检查功能实现这一目标的合理方法是定义一个新访问者,包括对 CreateInstance
的所有不同覆盖和签名:
public IEntitaTipoParametroEntita CreateInstance(SubType1 subType1)
{
// ...
}
public IEntitaTipoParametroEntita CreateInstance(SubType2 subType2)
{
// ...
}
每个子类型都应该有自己的
IEntitaTipoParametroEntita accept(CreateVisitor visitor)
{
visitor.CreateInstance(this);
}
这样您就可以避免 if
和 switch
以及类似的容易出错的子类型检查语法,而只需实例化特定的访问者,然后将其传递给要处理的任何子类型。
DB tables
如果子类型之间存在显着的共性,那么将子类型拆分为单独的物理 tables 可能没有什么价值。
因此,就数据库设计而言,“table per hierarchy”(利用类型鉴别器列来保存类型信息)似乎更适合您的示例:它通过对 SQL 模式进行非规范化来启用多态性。要指示 Entity Framework 使用此策略,只需从 DbContext
class 派生一个 class,然后添加一个 DBSet
属性 对于超类型,同时不为子类型添加 DBSet
属性。
阅读链接
我有一个工厂 class 和 CreateInstance 方法
CreateInstance(EntityModel.TipoEntitaTipoParametroEntita tipoParametroEntita, IParametroEntitaMultiValoreDataSourceProvider parametroEntitaMultiValoreDataSourceProvider)
工厂可以根据 tipoParametroEntita.TipoCampo.IdTipoCampo
重点是 CreateInstance
(parametroEntitaMultiValoreDataSourceProvider
) 的第二个参数仅用于创建 TipoEntitaTipoParametroEntitaMultiValore
的实例
while 不用于创建 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
。但我只想把这个逻辑放在一个地方。
从函数式编程的角度来看,在处理所谓的 "algebraic data types" 即不同的子类型时,我习惯于查看访问者模式。无论如何,我并不总是喜欢这种方法,因为一开始它可能很困难。
因此我只给出基本思路,以便您可以快速决定是否感兴趣。另请注意,此处的目标是编写具有函数签名的代码,以便可以在 compile 时间发现错误,与 runtime 相反。 =22=]
简而言之,class通过利用 C# 语言类型检查功能实现这一目标的合理方法是定义一个新访问者,包括对 CreateInstance
的所有不同覆盖和签名:
public IEntitaTipoParametroEntita CreateInstance(SubType1 subType1)
{
// ...
}
public IEntitaTipoParametroEntita CreateInstance(SubType2 subType2)
{
// ...
}
每个子类型都应该有自己的
IEntitaTipoParametroEntita accept(CreateVisitor visitor)
{
visitor.CreateInstance(this);
}
这样您就可以避免 if
和 switch
以及类似的容易出错的子类型检查语法,而只需实例化特定的访问者,然后将其传递给要处理的任何子类型。
DB tables
如果子类型之间存在显着的共性,那么将子类型拆分为单独的物理 tables 可能没有什么价值。
因此,就数据库设计而言,“table per hierarchy”(利用类型鉴别器列来保存类型信息)似乎更适合您的示例:它通过对 SQL 模式进行非规范化来启用多态性。要指示 Entity Framework 使用此策略,只需从 DbContext
class 派生一个 class,然后添加一个 DBSet
属性 对于超类型,同时不为子类型添加 DBSet
属性。