如何扩展类的字段?

本文关键字:字段 扩展 何扩展 | 更新日期: 2023-09-27 18:02:40

假设我有一个Person的列表(这是一个类)。它包含大约20个字段(Name、姓、Age、DateOfBirthdate等等)。所以我得到了这个列表:

var listOfPersons= MyContext.Persons.Cast<Person>();

现在,我需要遍历这个列表,并为每个Person添加一个新字段(它不存在于类中),假设称为CurrentDateTime

我可以用新字段创建一个新对象,并写上"copy &将"Person"的值粘贴到新的"Class"中。小明:

PersonNew newPerson = new PersonNew("Name", "Surname", "Age", "DateOfBirthdate", ... "CurrentDateTime");

但是,如果将来我更改Person类,这将是非常糟糕的。那么,是否存在一种将Person"扩展"到新领域的策略呢?它接受Person实例(无论它是什么)并添加新字段?

如何扩展类的字段?

您可以使用Automapper创建一些静态方法从Person创建PersonNew

public class PersonNew : Person
{
    public static PersonNew CreateFromPerson(Person person, DateTime currentDateTime)
    {
        var newPerson = Mapper.Map<PersonNew>(person);
        newPerson.CurrentDateTime = currentDateTime;
    }
}

我认为你描述的解决方案很好。如果您希望在不扩展Person类的情况下跟踪每个人的生日,则可以使用Dictionary对象

var listOfPersons = MyContext.Perons.Cast<Person>();
Dictionary<Person, DateTime> birthdays = new Dictionary<Person, DateTime>    
foreach(Person person in listOfPersons)
{
    birthdays.Add(person, getBirthday(person); 
}

一个解决方案是使您的类partial,并在您的类的另一个partial定义中添加您的字段:

public partial class Person
{
    public string Name { get; set; }
    public string FirstName { get; set; }
    ...
}
...
public partial class Person
{
    public DateTime CurrentDateTime { get; set; }
}
...
var listOfPersons = MyContext.Persons.Cast<Person>();
foreach (var person in listOfPersons)
{
    person.CurrentDateTime = ....
}

请注意,您将使用与类相同的实例。

首先,我建议使用扩展方法来投影集合,而不是迭代。像这样:

var newCollection = oldCollection.Select(entity => MakeNewType(entity))

第二,你所说的用新字段"扩展Person"是什么意思并不完全清楚。这里有几个方法可以让你做到这一点。

1)用新字段创建另一个类,并将其映射到旧的字段。这是asp.net mvc应用程序的常见场景,您将模型映射到适当的视图模型。Automapper对于这些类型的场景很有用(参见Sławomir Rosiek answer)

2)利用c# 4+中的dlr。您将失去动态对象的智能感,但它们可以在函数

中传递。
var newPeople = people.Select(p =>
    {
        dynamic expando = new ExpandoObject();
        expando.Id = p.Id;
        expando.FirtName = p.FirtName;
        /* ... */
        expando.CurrentDateTime = DateTime.Now;
        return expando;
    });

3)使用匿名类型。匿名类型不能传递给其他函数,所以当您需要在单个方法中快速投影数据并计算一些结果

时,此方法非常有用。
var newPeople = people.Select(p => new 
    { 
        Id = p.Id, 
        FirtName = p.FirtName, 
        /* ... */ 
        CurrentDateTime = DateTime.Now 
    });

在这两种情况下,你现在可以访问新创建的属性:

foreach(var p in newPeople)
{
    Console.WriteLine("CurrentDateTime: {0}", p.CurrentDateTime);
}

4)如果你真的需要在运行时创建一个功能齐全的。net类,你可以使用Reflection.Emit。此场景通常用于创建动态代理——实现某些仅在运行时才知道的功能的子类。