LWS
LWS

Reputation: 329

How to cast object to generic class without knowing T

I get my variable from var pi = propertyInfo.GetValue(instance) this is an object Type. I know all result of this are of type ObjectSet<TEntity> . I don't know TEntity. TEntity is allways different.

The consuming function looks alike:

BuildClassItem<T>(ObjectSet<T> entities, ... ) where T : class

How can I cast object to ObjectSet ?

I tried alredy this. But I don't know T

public static ObjectSet<T> MyConvert<T>(object myInput) where T : class
{
    return (ObjectSet<T>)myInput;
}

Upvotes: 1

Views: 1898

Answers (2)

TimChang
TimChang

Reputation: 2417

public class ObjectSet<T>
{
}

public static ObjectSet<T> MyConvert<T>(object myInput) where T : class
{
    return (ObjectSet<T>)myInput;
}

invoke like this :

ObjectSet<object> get =  MyConvert<object>(new ObjectSet<object>());

I'm not got any error , So what error for your case ??

or

public class FOO
{
}
public interface IObjectSet
{
}

public class ObjectSet<T> : IObjectSet
{
}

IObjectSet get =  MyConvert<FOO>(new ObjectSet<FOO>());

Upvotes: 0

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239646

You can use System.Linq.Expressions to construct a "trampoline" - a call into a method which is generic. Once you're inside that generic method, then you can start using T naturally when you need to talk about the type. Here I'm using BuildClassItem directly as the target for the trampoline:

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Exercise
{
    class Program
    {

        static void Main(string[] args)
        {
            var obj = GetObjectSet();
            //We know obj is an ObjectSet<T> for unknown T
            var t = obj.GetType().GetGenericArguments()[0];
            var parm = Expression.Parameter(typeof(object));
            var objectSet = typeof(ObjectSet<>).MakeGenericType(t);
            var method = typeof(Program).GetMethod("BuildClassItem", BindingFlags.Static | BindingFlags.NonPublic).MakeGenericMethod(t);

            var trampoline = Expression.Lambda(
                Expression.Call(null, method, Expression.Convert(parm,objectSet)), new[] {parm});
            var dele = (Action<object>) trampoline.Compile();
            dele(obj);
            Console.WriteLine("Done");
            Console.ReadLine();
        }

        static void BuildClassItem<T>(ObjectSet<T> entities) where T : class
        {
            Console.WriteLine("We made it!");
        }

        static object GetObjectSet()
        {
            return new ObjectSet<string>();
        }
    }

    internal class ObjectSet<T> where T:class
    {
    }
}

If you have more work to do between finding the type T and calling BuildClassItem you'd still want to put all of that logic inside a generic method in T and construct a void call into it. You can't "say" the name of the type from outside a generic method so you have no way of storing the returned value from your MyConvert function in a correctly typed variable. So you need to move all of the logic into it.

Upvotes: 1

Related Questions