新的重复类但在 C# 中少了一个属性?

Tam*_*yen 1 c# oop inheritance

假设我有一个类是

public class ClientModel
{
    [Required]
    public int Id { get; set; }
    [Required]
    [MinLength(2, ErrorMessage = "First name can not be shorter than 2 characters")]
    public string FirstName { get; set; }
    [Required]
    [MinLength(2, ErrorMessage = "Last name can not be shorter than 2 characters")]
    public string LastName { get; set; }
    public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想将 ClientModel Obj 传递给函数,但没有电子邮件值。这样做的有效方法是什么(除了忽略函数中的电子邮件)。有没有办法当场创建一个新类减去我们不需要的字段?

Chr*_*ler 5

OP 请通读XY 问题,我强烈怀疑您的问题有比您在这里要求的更好的解决方案。

类型继承

实现这一点的一种方法是通过继承,但这实际上与您期望的相反,c# 中的类型无法删除类型中定义的成员的定义,因此在此解决方案中我们创建ClientModel子类型!

  1. 将您当前的班级重命名为 ClientModelBase
  2. 添加一个名为ClientModel继承自的新类ClientModelBase
  3. 将电子邮件属性从 移动ClientModelBaseClientModel

结果如下所示:

public class ClientModelBase
{
    [Required]
    public int Id { get; set; }
    [Required]
    [MinLength(2, ErrorMessage = "First name can not be shorter than 2 characters")]
    public string FirstName { get; set; }
    [Required]
    [MinLength(2, ErrorMessage = "Last name can not be shorter than 2 characters")]
    public string LastName { get; set; }
}

public class ClientModel : ClientModelBase
{
    public string Email { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,在运行时,你可以投的实例为ClientModelClientModelBase,所以对于需要方法ClientModel 没有Email属性,设置参数类型ClientModelBase

// Get an instance of a client
ClientModel client = clientRepo.ByKey(123);
ProcessClientWithoutEmail(client);
...
public void ProcessClientWithoutEmail(ClientModelBase client)
{
    // client doesn't expose an Email property
}
Run Code Online (Sandbox Code Playgroud)

这种隐式转换技术类似于C# 值装箱,如果您在逻辑链的后面需要它,电子邮件属性在技术上仍然可以访问,我们已经有效地将掩码应用于对象,以便编译器仅将其视为基本类型,当或者如果您需要,并且仅当原始实例是ClientModel您可以将引用转换回ClientModel确实具有该Email属性的引用。


接口 [组成]

除了为 ClientModel创建要继承的基类之外,您还可以使用interface. 然而,这需要更多的代码来实现,因为您需要完全定义接口的原型。最终结果是相似的,它对原始模型的影响较小,因为唯一的变化是声明 ClientMode实现了新IClientModelName接口:

public class ClientModel : IClientModelName
{
    [Required]
    public int Id { get; set; }
    [Required]
    [MinLength(2, ErrorMessage = "First name can not be shorter than 2 characters")]
    public string FirstName { get; set; }
    [Required]
    [MinLength(2, ErrorMessage = "Last name can not be shorter than 2 characters")]
    public string LastName { get; set; }
    public string Email { get; set; }
}

public interface IClientModelName
{
    int Id { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这几乎与前面的代码示例相同,但有一个重要区别,虽然仍然可以 Cast back to ClientModel,但我们现在可以传递与 ClientModel 来自的 repo 无关的对象,因此这简化了单元测试或嘲笑。

如果您的生产代码已经具有复杂的继承或其他影响初始化的因素,您可能会发现使用接口的基于组合的解决方案更适合您的用例。

// Get an instance of a client
ClientModel client = clientRepo.ByKey(123);
ProcessClientWithoutEmail(client);
...
public void ProcessClientWithoutEmail(IClientModelName client)
{
    // client doesn't expose an Email property
}
Run Code Online (Sandbox Code Playgroud)