简体   繁体   English

如何扩展课程的领域?

[英]How can I extend a field of a class?

Suppose I have a List of Person (which is a class). 假设我有一个“ Person列表”(这是一个类)。 It contains about 20 field (Name, Surname, Age, DateOfBirthdate, and so on). 它包含大约20个字段(姓名,姓氏,年龄,出生日期等)。 So I got this list: 所以我得到了这个清单:

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

Now, I need to iterate through this List, and for each Person adding a new field (which it is not present in the class), called, let's say, CurrentDateTime . 现在,我需要遍历此List,并为每个Person添加一个新字段(该类在当前类中不存在),称为CurrentDateTime

I could create a new object, with the new field, and "copy & paste" values from Person to the new Class. 我可以使用新字段创建一个新对象,然后将Person中的值“复制并粘贴”到新的Class中。 Somethings like: 诸如此类的东西:

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

But this is very bad if in the future I change the Person class. 但是,如果将来我更改Person类,这将非常糟糕。 So, is there a strategy to "extending Person" with a new field? 那么,是否有一种策略可以在新领域“扩展人”? That takes the Person instance (whatever it is) and adds the new field? 那需要Person实例(无论它是什么)并添加新字段?

You can create some static method that create PersonNew from Person using Automapper. 您可以创建一些静态方法,以使用PersonNewPerson中创建PersonNew

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

I think that the solution you described works fine. 我认为您描述的解决方案效果很好。 If you want to keep track of each person's birthday without extending the Person class, you might use a Dictionary object 如果要在不扩展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); 
}

One solution is to make your class partial , and add your field in another partial definition of your class: 一种解决方案是使您的类成为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 = ....
}

Do note that you will use the same instance of your class. 请注意,您将使用类的相同实例。

First I would suggest using extension methods for projecting collections instead of iterating. 首先,我建议使用扩展方法来投影集合而不是进行迭代。 Like that: 像那样:

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

Second, it's not completely clear what you mean by "extending Person" with a new field. 其次,不清楚用新字段“扩展Person”是什么意思。 Here are the couple of ways you can accomplish that. 这是您可以完成此操作的两种方法。

1) Make another class with the new field and map it to the old one. 1)使用新字段创建另一个类,并将其映射到旧字段。 This is a common scenario for asp.net mvc application where you map models to the appropriate viewmodels. 这是asp.net mvc应用程序的常见方案,您可以在其中将模型映射到适当的视图模型。 Automapper is useful for these types of scenario (see Sławomir Rosiek anwser) 自动映射器对于这些类型的场景很有用(请参阅SławomirRosiek anwser)

2) Take advantage of dlr in c# 4+. 2)利用C#4+中的dlr。 Yuo will lose the intellisense for dynamic objects, but they canned be passed around functions 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) Use Anonymous types. 3)使用匿名类型。 Anonymous types cannot be passed to another functions, so this approach is useful when you need to quickly project data inside a single method and calculate some result 匿名类型无法传递给其他函数,因此当您需要在单个方法中快速投影数据并计算一些结果时,此方法很有用

var newPeople = people.Select(p => new 
    { 
        Id = p.Id, 
        FirtName = p.FirtName, 
        /* ... */ 
        CurrentDateTime = DateTime.Now 
    });

in both cases you can now access newly "created" property: 在这两种情况下,您现在都可以访问新创建的属性:

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

4) If you really need to create a fully featured .net class at runtime you can use Reflection.Emit . 4)如果您确实需要在运行时创建功能齐全的.net类,则可以使用Reflection.Emit This scenario is typically used to create dynamic proxies - subclasses which implement some functionality only known at runtime. 此方案通常用于创建动态代理-子类,这些子类实现某些仅在运行时才知道的功能。 Entity framework does this. 实体框架可以做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM