SharpShade
SharpShade

Reputation: 2183

Howto reflect object into an only at runtime known type

i have a little big problem.
My problem is the following.

I´ve got two types: AssetData and AssetData. They are basicly the same, but not inherited.
Now i have i know a property with the Type "AssetData", and i have a object of type AssetData (containing a Texture2D object).

Now i want to cast the AssetData object into the AssetData object. Because i don´t know the generic parameter, AssetData has now operator for that kind of cast, but AssetData is able to cast to AssetData.

I tried and tried what i could do to solve it, but i have no more ideas.

Here´s my situation: I´ve got a type of a property, i have a AssetData with the same object, but i must set the AssetData to the property - so i have to set "AssetData", not AssetData.

Here´s my code. I can´t hardcode it, because it would be to much to change after adding new types. That´s my latest try. It nearly works, but has the problem that the cast does not work, because there´s no operator of AssetData ...

foreach (PropertyInfo pinf in comp.GetType().GetProperties())
            {
                for (int i = 0; i < cdata.PInf.Count; i++)
                {
                    if (cdata.PInf[i] != pinf.Name) continue;

                    AssetData assetData = new AssetData
                                              {
                                                  AssetName = cdata.AN[i],
                                                  AssetType = Type.GetType(cdata.AT[i], true)
                                              };
                    Application.Game.GetSystem<ContentManager>().LoadContent(ref assetData);

                    if (pinf.PropertyType.IsGenericType)
                    {
                        MethodInfo method = typeof (DynamicCast).GetMethod("Cast").GetGenericMethodDefinition().MakeGenericMethod(
                                assetData.AssetType);

                        Type castedAssetType =
                            pinf.PropertyType.GetGenericTypeDefinition().MakeGenericType(assetData.AssetType);

                        dynamic castedAsset = method.Invoke(typeof (DynamicCast), new[] {assetData});

                        pinf.SetValue(comp, castedAsset, null);
                    }
                }
            }
        }

And here´s the method of "DynamicCast" - which i found on an blog. This also doesn´t work ...

    public static class DynamicCast
{
    public static T Cast<T>(object o)
    {
        Type ot = o.GetType();
        MethodInfo meth = GetMethod(ot, "op_Implicit", typeof(T),
            BindingFlags.Static | BindingFlags.Public);
        if (meth == null)
        {
            meth = GetMethod(ot, "op_Explicit", typeof(T),
                BindingFlags.Static | BindingFlags.Public);
        }

        if (meth == null) throw new InvalidCastException("Invalid Cast.");

        return (T) meth.Invoke(null, new[] {o});
    }

    public static MethodInfo GetMethod(Type toSearch, string methodName,
        Type returnType, BindingFlags bindingFlags)
    {
        return Array.Find(
            toSearch.GetMethods(bindingFlags),
            inf => ((inf.Name == methodName) && (inf.ReturnType == returnType)));
    }
}

The problem is, that i must create an AssetData object (in this case), and set it as value for the property. But the object is clear, so i must cast AssetData´s "Asset"-property to the "AssetData"´s. Both are the same type, but one is "object" and one "T" (Texture2D).

How can i cast this?

Thanks a lot! I´m workin on this since the midday ...

Upvotes: 1

Views: 836

Answers (2)

SharpShade
SharpShade

Reputation: 2183

I got the solution...

I just had to add an generic method "Cast()" to AssetData. I just came on this idea, because now i know i can invoke a generic method ;)

Here´s the solution:

if (pinf.PropertyType.IsGenericType)
{
    MethodInfo method =
        assetData.GetType().GetMethod("Cast").GetGenericMethodDefinition().MakeGenericMethod(
            assetData.AssetType);

    dynamic castedAsset = method.Invoke(assetData, null);

    pinf.SetValue(comp, castedAsset, null);
}

Upvotes: 1

Timwi
Timwi

Reputation: 66614

Just use dynamic.

public static class DynamicCast
{
    public static T Cast<T>(object o)
    {
        return (T) (dynamic) o;
    }
}

This will automatically use any implicit/explicit operators that exist on the run-time type of o and/or the type T. (Your code is incomplete because you’re searching only one of the two.)

The rest of your question is extremely unclear. You need to rephrase it. The code is also unclear: what is the variable castedAssetType for? You are only assigning to it but then not using it.

Upvotes: 1

Related Questions