在EntityTypeConfiguration <t>?</t>的构造函数中调用虚方法有多大的风险

时间:2013-12-24 11:02:14

标签: c# entity-framework oop

我有一个所有实体类的基类:

public class XTimeEntityTypeConfiguration<TEntity> : EntityTypeConfiguration<TEntity> where TEntity : XTimeEntity
{
  public XTimeEntityTypeConfiguration()
  {
      this.HasKey(t => t.Id);
      this.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);        
      this.Ignore(t => t.IsActive);
  }
}

现在我想使这个默认行为可以覆盖,因为在某些实体类中需要逻辑来确定它是如何完成的,例如:哪个属性是关键。我也想制作配置的其他部分,我不能覆盖构造函数,所以考虑从构造函数调用虚方法,完全了解这个的气味,但也相当自信这个基类的继承深度将几乎总是只有一个,即每个实体一个派生的实现。我建议的基类类似于:

public abstract class XTimeEntityTypeConfiguration<TEntity> : EntityTypeConfiguration<TEntity> where TEntity : XTimeEntity
{
  protected XTimeEntityTypeConfiguration()
  {
    ConfigureProperties();
    ConfigureRelationships();
    ConfigureTableMapping();
    ConfigureKey();
    ConfigureColumnMappings();
  }

  protected virtual void ConfigureKey()
  {
    this.HasKey(t => t.Id);
    this.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
  }

  protected virtual void ConfigureTableMapping()
  {
    var plurals = PluralizationService.CreateService(CultureInfo.CurrentCulture);
    this.ToTable(plurals.Pluralize(GetType().Name));
  }

  protected virtual void ConfigureColumnMappings() { }
  protected virtual void ConfigureProperties() { }
  protected virtual void ConfigureRelationships() { }
  protected virtual void ConfigureIgnores()
  {
    this.Ignore(t => t.IsActive);
  }
}

派生的实例:

public class ActivityMap : XTimeEntityTypeConfiguration<Activity>
{
  public ActivityMap() : base() {}

  protected override void ConfigureProperties()
  {
    base.ConfigureProperties();
    this.Property(t => t.Name)
      .IsRequired()
      .HasMaxLength(30);
  }

  protected override void ConfigureColumnMappings()
  {
    base.ConfigureColumnMappings();
    this.Property(t => t.Id).HasColumnName("ACT_CODEID");
  }

  protected override void ConfigureTableMapping()
  {
    this.ToTable("ACTIVITY");
  }
}

1 个答案:

答案 0 :(得分:1)

也许你最好在这里使用Decorator Pattern。您可以将配置行为保留给装饰器,这样就不会出现虚拟混乱:)

在这种情况下,使用装饰器基类,并从中派生出类似于:

的类
public abstract class EntityConfigurationBehavior
{
    public abstract void Configure<TEntity>(EntityTypeConfiguration<TEntity> config);
}

public class DefaultConfigurationBehavior : EntityConfigurationBehavior
{
    public override void Configure<TEntity>(EntityTypeConfiguration<TEntity> config)
    {
        config.HasKey(t => t.Id);
        config.Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);        
        config.Ignore(t => t.IsActive);
    }
}

在您的配置类中,拥有带有配置的受保护字段或属性:

public abstract class XTimeEntityTypeConfiguration<TEntity> : EntityTypeConfiguration<TEntity> where TEntity : XTimeEntity
{
    // [...]

    protected EntityConfigurationBehavior ConfigurationBehavior { get; set; }

    // [...]
}

现在你可以调用它来设置它:

public class ActivityMap : XTimeEntityTypeConfiguration<Activity>
{
    public ActivityMap() : base() 
    {
        ConfigurationBehavior = new DefaultConfigurationBehavior(this);
    }
}

如果您需要更多配置选项,您可以随时创建更多行为,或者如果这样做太乱,请列出您可以配置的行为。我没有制作 EntityConfigurationBehavior 泛型,因为您正在寻找一种配置所有常用属性的方法。您可以在ActivityMap本身中配置特定于 Activity 的属性。