我怎样才能扩展一个类的字段?

时间:2013-03-06 16:11:58

标签: c# .net linq extend

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

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

现在,我需要迭代这个List,并为每个Person添加一个新字段(它不在课堂中),叫做CurrentDateTime

我可以使用新字段创建一个新对象,并将Person中的“复制和粘贴”值复制到新类。有些事情喜欢:

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

但如果将来我更改Person类,这是非常糟糕的。那么,是否有一个“扩展人”的战略?这需要Person实例(无论它是什么)并添加新字段?

4 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

我认为您描述的解决方案运行正常。如果你想在不扩展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); 
}

答案 2 :(得分:0)

一种解决方案是让您的课程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 = ....
}

请注意,您将使用班级的相同的实例。

答案 3 :(得分:0)

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

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

其次,通过新领域“扩展人”并不完全清楚你的意思。以下是您可以通过以下几种方式实现这一目标。

1)使用新字段创建另一个类并将其映射到旧字段。这是asp.net mvc应用程序的常见场景,您可以将模型映射到相应的视图模型。 Automapper对这些类型的场景非常有用(参见SławomirRosiekanwser)

2)利用c#4+中的dlr。 Yuo将失去动态对象的智能感知,但它们可以通过函数传递

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。此方案通常用于创建动态代理 - 实现仅在运行时已知的某些功能的子类。实体框架就是这样做的。