我如何在运行时创建子类来映射一些属性,然后将其转换回父类

本文关键字:然后 属性 父类 转换 运行时 创建 映射 子类 | 更新日期: 2023-09-27 18:11:48

考虑这个People类:

public class People
{
    public virtual string Name { get; set; }    
    public virtual ushort Age { get; set; }
}

我有一些第三方实现,可以获得人们的数据,但有一点变化。例如,我有一个能够检索StrangePeople数据的方法:

    public class StrangePeople
    {
        public string Name { get; set; }        
        public DateTime BirthDate { get; set; }
    }
    ...
    StrangePeople someone = GetData<StrangePeople>();

由于类和变化的数量,我试图找到一种方法来生成People的运行时子类,可以翻译数据,所以我可以稍后将其转换回People。换句话说,以最小的工作量生成如下的子类:

public class StrangePeopleTranslator : People
{
    private ushort? _mAge = null;
    public override ushort Age
    {
        get
        {
            if (_mAge == null)
            {
                DateTime today = DateTime.Today;
                int age = today.Year - BirthDate.Year;
                if (BirthDate > today.AddYears(-age)) age--;
                _mAge = age;
            }
            return _mAge.GetValueOrDefault();
        }
        set
        {
            _mAge = value;
        }
    }
    public DateTime BirthDate { get; set; }
}
...
People someoneElse = (People)GetData<StrangePeopleTranslator>();

也许运行时子类有点过分了…我不知道。

我如何在运行时创建子类来映射一些属性,然后将其转换回父类

您能做的最好的事情就是提供隐式强制转换重载。这样就可以将StrangePeople转换为People,如下所示:

public class StrangePeople
{
    public string Name { get; set; }
    public DateTime BirthDate { get; set; }
    public static implicit operator People(StrangePeople strangePerson)
    {
        DateTime today = DateTime.Today;
        int age = today.Year - strangePerson.BirthDate.Year;
        if (strangePerson.BirthDate > today.AddYears(-age))
        {
            age--;
        }
        return new People
                    {
                        Name = strangePerson.Name,
                        Age = (ushort) age
                    };
    }

那么你可以这样做:

People someoneElse = GetData<StrangePeopleTranslator>();

好吧,这取决于你愿意付出多少努力,你可以使用一个子类与动态生成的Func s使用System.Linq.Expressions.,你需要使用c# 4在这里的全部功能。

基本思路:

public class Subclass : People
{
    public Func<DateTime, ushort> BirthDateToAge;
    ushort _mAge;
    public override ushort Age
    {
        get { return AgeImpl(_mAge); }
        set { _mAge = value; }
    }
}
// And then somewhere else where you'd want to create the "subclass"
var people = new Subclass();
Func<DateTime, ushort> setter = (Func<DateTime, ushort>)(bday => (ushort)CalcElapsedYears(bday));
people.AgeImpl = setter;

你可能需要以不同的方式考虑它,但基本概念是相同的:创建一个可以完全通过Func<> s操作的泛型子类,然后在进行反射或其他操作时构建这些Func<> s。