C# Use System.Type as Generic Parameter

C# use System.Type as Generic parameter

You can't, directly. The point of generics is to provide compile-time type safety, where you know the type you're interested in at compile-time, and can work with instances of that type. In your case, you only know the Type so you can't get any compile-time checks that any objects you have are instances of that type.

You'll need to call the method via reflection - something like this:

// Get the generic type definition
MethodInfo method = typeof(Session).GetMethod("Linq",
BindingFlags.Public | BindingFlags.Static);

// Build a method with the specific type argument you're interested in
method = method.MakeGenericMethod(typeOne);
// The "null" is because it's a static method
method.Invoke(null, arguments);

If you need to use this type a lot, you might find it more convenient to write your own generic method which calls whatever other generic methods it needs, and then call your method with reflection.

Pass An Instantiated System.Type as a Type Parameter for a Generic Class

You can't do this without reflection. However, you can do it with reflection. Here's a complete example:

using System;
using System.Reflection;

public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}

class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);

Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);

object created = Activator.CreateInstance(constructedClass);
}
}

Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:

Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);

How can a `System.Type` be a generic parameter with constraints?

The following code works for me:

public class Service {
public void Fn<T>() where T : I, new() {
(new T()).M();
// ...
}
}
public interface I
{
void M();
}

public class C : I
{
public void M();
}
public class D : I
{
public void M();
}

static void Main()
{
var service = new Service();
service.Fn<C>();
service.Fn<D>();
}

The issue was the superfluous Type in the where clause. T is a Type anyway by the fact it is a generic parameter - but an object of type A or B wouldn't be castable to the Type class - this is what where T : Type would mean.

In general, where T: X, Y, Z means that any T must (depending on what X, Y and Z are) either implement the interface, or be a subclass of, X, Y and Z. The new() constraint is slightly different, and makes the compiler aware that you also wish to be able to create a new object of type T in the method. (see http://msdn.microsoft.com/en-gb/library/bb384067.aspx and http://msdn.microsoft.com/en-gb/library/d5x73970.aspx for more details)

Also, I've removed typeOf() from your input, as when you're using a generic the type can be referenced directly in the function (see above). Hope that makes sense. Any questions, just ask!

Passing Type parameter to generic in C#

You can use MakeGenericType method to create a generic type using a Type instance:

var type = typeof(ValueCriterion<>).MakeGenericType(myType);

var instance = Activator.CreateInstance(type, 0);

passing System.Type to generic type

var table = TableInfo.GetValue(_context) as DbSet<[here i need pass it]>;

You can't do that, you have no compile time information on what type you need, how do you expect to leverage it before the code is even running?

If you really want compile time type information of table you either know the generic type at compile time or you cover all possible execution paths considering all potential generic types your method must handle (horrendous, don't do that).

Using an interface won't work either. A hypothetical IIdEntity and a cast along the lines table as DbSet<IIdEntity> will never work because:

  1. Type variance is only allowed in interfaces and delegates, DbSet is not an interface.
  2. Even if you use IDbSet<TEntity>, this interface is invariant in TEntity so the following will always fail:

    class User: IIdEntity { ... }
    object o = someDbEntityOfUser;
    var db = o as IDbSet<IIdEntity> //will always be null.

The best options you have with your current setup are:

  1. Keep using reflection; use it to inspect the Id property of the entities.
  2. Use dynamic and simply let the runtime resolve the Id call.

Using System.Type to call a generic method

Try to use next code snippet to see if it meets your need. It creates a close typed instance of method public static void Serialize<T>(Stream destination, T instance). In this case it select the first method with Stream as parameter, but you can change this predicate method.GetParameters().Any(par => par.ParameterType == typeof(Stream)) to whatever you want

public static object DeserializeReflection(Stream stream, object instance)
{
return typeof(Serializer)
.GetMethods()
.First(method => method.Name == "Serialize" && method.GetParameters().Any(par => par.ParameterType == typeof(Stream)))
.MakeGenericMethod(instance.GetType())
.Invoke(null, new object[] { stream, instance });
}

Using Type objects as Type Parameters for Generics in C#

You can dynamically create an instance of the type :

public void test()
{
Type someType = getSomeType(); // get some System.Type object
Type openType = typeof(MyGeneric<>);
Type actualType = openType.MakeGenericType(new Type[] { someType });
object obj = Activator.CreateInstance(actualType);
}

However you can't declare a variable of this type, since you don't know the actual type statically.



Related Topics



Leave a reply



Submit