Can reflection be used to instantiate an objects b

2019-04-30 00:01发布

问题:

Like this:

    public class remoteStatusCounts : RemoteStatus 
{
    public int statusCount;

    public remoteStatusCounts(RemoteStatus r)
    {
        Type t = r.GetType();
        foreach (PropertyInfo p in t.GetProperties())
        {
            this.property(p) = p.GetValue(); //example pseudocode
        }
    }
}

The example is a bit simple (it's from the Jira API - RemoteStatus has 4 properties), but imagine the base class had 30 properties. I don't want to manually set all those values, especially if my inherited class only has a couple of extra properties.

Reflection seems to hint at an answer.

I saw at Using inheritance in constructor (publix X () : y) that I can call the base class constructor (I think? correct me if I'm wrong), but my base class doesn't have a constructor - it's derived from the jira wsdl

        public remoteStatusCounts(RemoteStatus r) : base(r) { //do stuff }

edit I can imagine 2 valid solutions: the one outlined above, and some sort of keyword like this.baseClass that is of type(baseclass) and manipulated as such, acting as a sort of pointer to this. So, this.baseClass.name = "Johnny" would be the exact same thing as this.name = "Johnny"

For all intents and purposes, let's assume the baseclass has a copy constructor - that is, this is valid code:

        public remoteStatusCounts(RemoteStatus r) {
            RemoteStatus mBase = r;
            //do work
        }

edit2 This question is more of a thought exercise than a practial one - for my purposes, I could've just as easily done this: (assuming my "baseclass" can make copies)

    public class remoteStatusCounts 
{
    public int statusCount;
    public RemoteStatus rStatus;
    public remoteStatusCounts(RemoteStatus r)
    {
        rStatus = r;
        statusCount = getStatusCount();
    }
}

回答1:

Yes, you can do this - be aware though, that you might run into getter-only properties which you have to deal with seperately.

You can filter it with the Type.GetProperties(BindingsFlags) overload.

Note: You probably should look into code generation (T4 would be an idea, as it is delivered with vs 2008/2010), because reflection could have runtime-implications like execution speed. With codegeneration, you can easily handle this tedious work and still have the same runtime etc like typing it down manually.

Example:

//extension method somewhere
public static T Cast<T>(this object o)
{
    return (T)o;
}

public remoteStatusCounts(RemoteStatus r)
{
    Type typeR = r.GetType();
    Type typeThis = this.GetType();

    foreach (PropertyInfo p in typeR.GetProperties())
    {
        PropertyInfo thisProperty = typeThis.GetProperty(p.Name);

        MethodInfo castMethod = typeof(ExMethods).GetMethod("Cast").MakeGenericMethod(p.PropertyType);
        var castedObject = castMethod.Invoke(null, new object[] { p.GetValue(r, null) });
        thisProperty.SetValue(this, castedObject, null);
    }
}


回答2:

Try AutoMapper.