简体   繁体   English

如何在运行时创建子类以映射某些属性,然后将其强制转换回父类?

[英]How can I create subclass at run-time to map some properties then cast it back to parent class?

Consider this People class: 考虑一下这个People类:

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

I have some third party implementations that can obtain people data but with a little variations. 我有一些第三方实现可以获取人员数据,但有一些变化。 For example, I have a method that is able to retrieve data for StrangePeople : 例如,我有一个能够检索StrangePeople数据的StrangePeople

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

Due to the amount of classes and variations I trying to found a way to generate a runtime subclass of People that can translate the data so I can cast it back to People later. 由于类和变量的数量,我试图找到一种方法来生成可以转换数据的People的运行时子类,以便我可以稍后将其转发给People In other words, with minimum effort generate a subclass like this: 换句话说,用最少的努力生成如下的子类:

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>();

Maybe the run-time subclass it's bit overkill... I don't know. 也许运行时子类有点矫枉过正......我不知道。

The best thing you can do is provide an implicit cast overload. 您可以做的最好的事情是提供隐式转换过载。 That way you can convert from StrangePeople to People , like this: 这样你可以从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
                    };
    }

Then you could do this: 然后你可以这样做:

People someoneElse = GetData<StrangePeopleTranslator>();

You don't even need a cast. 你甚至不需要演员。

Well, depending on how much effort you're willing to put in to this, you could use a single subclass with dynamically generated Func s using System.Linq.Expressions. 好吧,根据您愿意投入多少精力,您可以使用System.Linq.Expressions.动态生成Func的单个子类System.Linq.Expressions. You'll need to be using C#4 for full functionality here. 您需要在此处使用C#4来获得完整功能。

The basic idea: 基本理念:

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;

You'll probably need to factor it differently, but the basic concept is the same: create a generic subclass that can operate entirely via Func<> s, and then build those Func<> s when you do your reflection or whatnot. 您可能需要以不同的方式对其进行分析,但基本概念是相同的:创建一个可以完全通过Func<> s运行的通用子类,然后在进行反射或诸如此类的东西时构建那些Func<>

It's kind harebrained, but it should work. 它是善良的,但它应该工作。

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

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