c# - 将派生类型传递给重构方法

标签 c# parameter-passing generic-type-argument

在我的 EF Fluent API 配置中,我有许多派生自抽象基类的类

public abstract class ImageBase
{
    public int ImageId { get; set; }
    public string ImageTitle { get; set; }
    public string ImageFileExtension { get; set; }
    public string ImageDescription { get; set; }
    [NotMapped]
    public string ImageFileName => BuildImageFilename();
    public string ImageUrl { get; set; }

    //set this property to true when part of a collection
    //if it is the main image of the collection
    public bool IsMainImage { get; set; }

    //for consistency, all image filenames are the image title, with spaces replaced with underscores
    //and the image file extension
    private string BuildImageFilename()
    {
        return $"{ImageTitle.Replace(" ", "_")}{ImageFileExtension}";
    }
}

我有许多派生自此的类,下面是一个例子

 public class ArticleImageUri : ImageBase
{
    [Required]
    public int ArticleId { get; set; }
}

在我那个类的流利 API 中,我最初有以下内容

public void Configure(EntityTypeBuilder<ArticleImageUri> builder)
    {
        //configure primary key
        builder.HasKey(u => new { u.ImageId, u.ArticleId })
            .HasName("PK_ArticleImageUri");

        //configure properties
        builder.Property(u => u.ArticleId)
           .ValueGeneratedNever()
           .IsRequired();

        builder.Property(u => u.ImageId)
          .ValueGeneratedOnAdd()
          .IsRequired();

        builder.Property(u => u.ImageDescription)
           .HasMaxLength(ConfigurationHelpers.MaxStringLengths.Descriptions)
           .IsRequired();

        builder.Property(u => u.ImageFileExtension)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.ShortText)
            .IsRequired();

        builder.Property(u => u.ImageTitle)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.FileNames)
            .IsRequired();

        builder.Property(u => u.ImageFileName)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.FileNames)
            .IsRequired();

        builder.Property(u => u.ImageUrl)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.Urls)
            .IsRequired();

        //ConfigurationHelpers.SetColumnSizesForImageClasses(builder);
    }

注意:ConfigurationHelpers.MaxStringLengths 是一个静态类,它返回一个表示列大小的 int。 我将 API 代码重构为方法 SetColumnSizesForImageClasses。

 public static void SetColumnSizesForImageClasses(EntityTypeBuilder<ArticleImageUri> builder)
    {
        //configure column sizes
        builder.Property(u => u.ImageDescription)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.Descriptions)
            .IsRequired();

        builder.Property(u => u.ImageFileExtension)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.ShortText)
            .IsRequired();

        builder.Property(u => u.ImageTitle)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.FileNames)
            .IsRequired();

        builder.Property(u => u.ImageFileName)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.FileNames)
            .IsRequired();

        builder.Property(u => u.ImageUrl)
            .HasMaxLength(ConfigurationHelpers.MaxStringLengths.Urls)
            .IsRequired();
    }

这很好用;仅针对本类(class)。

我认为只要传入构建器就可以工作,因为构建器已经是类型,但这是行不通的。 例如,我有一些其他派生图像类型。

 public class MachineImageUri : ImageBase
{
    [Required]

    public int MachineId { get; set; }

    public byte[] ImageThumbnail { get; set; }
}

我希望能够使用重构方法为每个派生类型 Fluent API 配置中的重复字段定义列大小,但我不知道如何传递正确的参数。我尝试使用 T,我认为这是可行的方法,但无法使用它的任何变体。

最佳答案

EntityTypeBuilder<T>是不变的,你将无法重用 Configure开箱即用的方法。换句话说,您仍然需要两个(或更多)不同的 EF 模型配置。

你可以做的是创建“助手”方法,它将接受任何 T具有一定的类型约束。

static void ConfigureBase<T>(EntityTypeBuilder<T> builder) where T : ImageBase
{
   builder.Property(u => u.ImageDescription)
        .HasMaxLength(ConfigurationHelpers.MaxStringLengths.Descriptions)
        .IsRequired();

    builder.Property(u => u.ImageFileExtension)
        .HasMaxLength(ConfigurationHelpers.MaxStringLengths.ShortText)
        .IsRequired();

    builder.Property(u => u.ImageTitle)
        .HasMaxLength(ConfigurationHelpers.MaxStringLengths.FileNames)
        .IsRequired();

    builder.Property(u => u.ImageFileName)
        .HasMaxLength(ConfigurationHelpers.MaxStringLengths.FileNames)
        .IsRequired();

    builder.Property(u => u.ImageUrl)
        .HasMaxLength(ConfigurationHelpers.MaxStringLengths.Urls)
        .IsRequired();
}

然后您就可以通过以下方式重用它:

ArticleImageUri配置:

public void Configure(EntityTypeBuilder<ArticleImageUri> builder)
{
   ConfigureBase<ArticleImageUri>(builder);
   //other specific configurations
}

MachineImageUri配置:

public void Configure(EntityTypeBuilder<MachineImageUri> builder)
{
   ConfigureBase<MachineImageUri>(builder);
   //other specific configurations
}

关于c# - 将派生类型传递给重构方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54129004/

相关文章:

java - 为什么可变参数应该是方法签名中的最后一个?

c - 函数指针作为常量参数

c# - 为什么接口(interface)不能用作类型参数?

java - Java 类构造函数中尖括号的用途是什么?

c# - 反序列化具有未知对象名称的 JSON

c# - 如何控制 IEnumerable 的更新

c# - Doxygen 只包含接口(interface)

c# - 使用 Moq 和 Unity 模拟存储库对象以进行单元测试的正确方法

java - 在组件之间传递值

java - 泛型 super 与扩展