如何将对象反映为仅在运行时已知类型

时间:2011-04-09 21:15:33

标签: c# generics reflection types casting

我有一个大问题 我的问题如下。

我有两种类型:AssetData和AssetData。它们基本相同,但不是遗传的 现在我知道一个类型为“AssetData”的属性,我有一个AssetData类型的对象(包含一个Texture2D对象)。

现在我想将AssetData对象强制转换为AssetData对象。因为我不知道泛型参数,所以AssetData现在具有这种类型转换的运算符,但AssetData能够转换为AssetData。

我尝试并尝试了解决它的方法,但我没有更多的想法。

这是我的情况:我有一种属性,我有一个具有相同对象的AssetData,但我必须将AssetData设置为属性 - 所以我必须设置“AssetData”,而不是AssetData。

这是我的代码。我无法对其进行硬编码,因为添加新类型后会有很多变化。这是我最近的尝试。它几乎可以工作,但是有一个问题,即转换不起作用,因为没有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);
                    }
                }
            }
        }

这是“DynamicCast”的方法 - 我在博客上找到了它。这也行不通......

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

问题是,我必须创建一个AssetData对象(在本例中),并将其设置为属性的值。但是对象很清楚,所以我必须将AssetData的“Asset”属性转换为“AssetData”。两者都是相同的类型,但一个是“对象”,一个是“T”(Texture2D)。

我怎么能投这个?

非常感谢!我从中午开始就在这里工作......

2 个答案:

答案 0 :(得分:1)

只需使用dynamic

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

这将自动使用运行时类型o和/或类型T上存在的任何隐式/显式运算符。 (您的代码不完整,因为您只搜索其中一个。)

你的其余问题非常不清楚。你需要改写它。代码也不清楚:变量castedAssetType是什么?您只是分配给它但后来没有使用它。

答案 1 :(得分:1)

我得到了解决方案......

我只需要在AssetData中添加一个通用方法“Cast()”。我刚刚提出这个想法,因为现在我知道我可以调用泛型方法;)

以下是解决方案:

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