SirZoro
SirZoro

Reputation: 151

Dynamically pass Type to Method<T>

I've a method , that retrieves to me some data according to some type I passed in parameter, like this :

    protected void FillList<TEntity>()
    {
        doWorkForTEntity();
    }

I Need to dynamically call this method :

            Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
            Type currentEntity = (from entity in entities
                                  where entity.Name.Equals(this.targetEntity)
                                  select entity).FirstOrDefault();
            FillList<currentEntity>();

I got this error :

The type or namespace name 'currentEntity' could not be found (are you missing a using directive or an assembly reference?)

I've tried an intermediate object type, no success

Any Idea please ?

Upvotes: 2

Views: 863

Answers (4)

qujck
qujck

Reputation: 14578

Change your method to take an instance of the Type TEntity:

protected void FillList<TEntity>(TEntity instance)
{
    doWorkForTEntity();
}

Create a dynamic instance from the Type name and then call the modified method:

dynamic instance = Activator.CreateInstance(this.targetEntity);
FillList(instance);

The dynamic type is basically doing what the other answers have shown you - but IMHO this code is neater and clearer in its intent.

Upvotes: 0

Yochai Timmer
Yochai Timmer

Reputation: 49269

You need to do that with reflection as well, so it won't fail in compile time (compiler checks):

Generic class:

Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
                           where entity.Name.Equals(this.targetEntity)
                           select entity).FirstOrDefault();
 Type fillListType= typeof(FillList<>);
 Type constructedGenericClass = fillListType.MakeGenericType(currentEntity);
 object myList = Activator.CreateInstance(constructedGenericClass );

Generic Method:

Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
                           where entity.Name.Equals(this.targetEntity)
                           select entity).FirstOrDefault();
MethodInfo methodinfo = this.GetType().GetMethod("FillList");
MethodInfo genericMethod = method.MakeGenericMethod(currentEntity);
genericMethod.Invoke(this, null);

Upvotes: 1

tukaef
tukaef

Reputation: 9224

Since there is no information about entity type in compile time, you need to construct and call appropriate method by reflection:

Type[] entities = System.Reflection.Assembly.GetAssembly(typeof(User)).GetTypes();
Type currentEntity = (from entity in entities
                      where entity.Name.Equals(this.targetEntity)
                      select entity).FirstOrDefault();     
var method = this.GetType().GetMethod("FillList",  BindingFlags.Instance | BindingFlags.NonPublic)
                           .MakeGenericMethod(currentEntity);
method.Invoke(this, new object[0]);

Upvotes: 2

Mecaveli
Mecaveli

Reputation: 1565

Type parameters must be specified at compile time and can´t be assigned at runtime like in your example. You get the error message because there´s no Type called currentEntiry since it´s just a variable.

Upvotes: 0

Related Questions