我可以使用泛型来推断已知类型的实际类型吗?

JAM*_*EME 5 c# generics reflection serialization json

我想做的事:使用Activator动态创建一个对象(可以是任何类型)并将其传递给序列化JSON的方法.注意:我已经看过使用泛型扩展方法的无类型推断,但这并没有真正给我任何有关如何解决这个问题的有用信息.

编辑:使用.NET 3.5 Framework

问题:我收到的对象可能是一个数组(例如int []),当我使用泛型来键入接收到的对象时,我得到一个对象[]而不是int [].

代码示例:

class Program
{
    static void Main(string[] args)
    {
        object objArr = new int[0];
        int[] intArr = new int[0];
        string arrS = "[1,2]";

        object objThatIsObjectArray = Serialize(objArr, arrS);//I want this to evaluate as int[]
        object objThatIsIntArray = Serialize(intArr, arrS);//this evaluates as int[]

        Console.Read();
    }
    public static object Serialize<T>(T targetFieldForSerialization, string value)
    {
        return value.FromJson<T>();
    }

}

public static class JSONExtensions
{
    public static TType FromJson<TType>(this string json)
    {
        using (var ms = new MemoryStream(Encoding.Default.GetBytes(json)))
        {
            var ser = new DataContractJsonSerializer(typeof(TType));
            var target = (TType)ser.ReadObject(ms);

            ms.Close();

            return target;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 5

没有自动的方法来做,如果你"认为"一个对象可能是int[]你可以尝试使用它as并检查结果是否为空;

static void Main(string[] args)
{
    object objArr = new int[0];
    string arrS = "[1,2]";

    int[] testArr = objArr as int[];

    if(testArr != null)
        object objThatIsIntArray = Serialize(testArr, arrS);//this evaluates as int[]
    else
        object objThatIsObjectArray = Serialize(objArr, arrS); //this evaluates as object because it could not figure out what it was.

    Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

如果您知道类型可能只是少数几种选择中的一种,您可以将其与其他if测试链接起来,每种类型一种.

这种模式在处理接口时非常常见,例如,这里是如何在Count()内部实现LINQ的方法,它检查类是否实现,ICollection<TSource>或者ICollection它可以使用该接口的Count属性.

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    ICollection<TSource> collection = source as ICollection<TSource>;
    if (collection != null)
    {
        return collection.Count;
    }
    ICollection collection2 = source as ICollection;
    if (collection2 != null)
    {
        return collection2.Count;
    }
    int num = 0;
    checked
    {
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                num++;
            }
        }
        return num;
    }
}
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用.GetType()获取Type并将其传递而不是隐式检测它,尽管我不知道如何处理FromJson我的头顶的返回类型.

class Program
{
    static void Main(string[] args)
    {
        object objArr = new int[0];
        int[] intArr = new int[0];
        string arrS = "[1,2]";

        object objThatIsObjectArray = Serialize(objArr.GetType(), arrS);//this evaluates as int[]
        object objThatIsIntArray = Serialize(intArr.GetType(), arrS);//this evaluates as int[]

        Console.Read();
    }
    public static object Serialize<T>(Type type, string value)
    {
        return value.FromJson(type);
    }

}

public static class JSONExtensions
{
    public static object FromJson(this string json, Type type)
    {
        using (var ms = new MemoryStream(Encoding.Default.GetBytes(json)))
        {
            var ser = new DataContractJsonSerializer(type);
            var target = ser.ReadObject(ms);

            ms.Close();

            return target;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)