Passar um sistema instanciado. Digite como um parâmetro de tipo para uma class genérica

O título é meio obscuro. O que eu quero saber é se isso é possível:

string typeName = ; Type myType = Type.GetType(typeName); MyGenericClass myGenericClass = new MyGenericClass(); 

Obviamente, MyGenericClass é descrito como:

 public class MyGenericClass 

No momento, o compilador reclama que ‘O tipo ou namespace’ myType ‘não pôde ser encontrado. “Tem que haver uma maneira de fazer isso.

Você não pode fazer isso sem reflection. No entanto, você pode fazer isso com reflection. Aqui está um exemplo completo:

 using System; using System.Reflection; public class Generic { 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); } } 

Nota: se sua class genérica aceita vários tipos, você deve include as vírgulas quando omitir os nomes de tipos, por exemplo:

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

Infelizmente não há não. Argumentos genéricos devem ser resolvidos no tempo de compilation como 1) um tipo válido ou 2) outro parâmetro genérico. Não há como criar instâncias genéricas baseadas em valores de tempo de execução sem o grande impacto do uso da reflection.

Minhas exigências eram um pouco diferentes, mas espero ajudar alguém. Eu precisava ler o tipo de uma configuração e instanciar o tipo genérico dinamicamente.

 namespace GenericTest { public class Item { } } namespace GenericTest { public class GenericClass { } } 

Finalmente, aqui está como você chama isso. Defina o tipo com um backtick .

 var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest"); var a = Activator.CreateInstance(t); 

Alguns adicionais como executar com código de tesoura. Suponha que você tenha uma aula semelhante a

 public class Encoder() { public void Markdown(IEnumerable contents) { do magic } public void Markdown(IEnumerable contents) { do magic2 } } 

Suponha que em tempo de execução você tenha um FooContent

Se você fosse capaz de ligar em tempo de compilation você iria querer

 var fooContents = new List(fooContent) new Encoder().Markdown(fooContents) 

No entanto, você não pode fazer isso em tempo de execução. Para fazer isso em tempo de execução, você faria o seguinte:

 var listType = typeof(List<>).MakeGenericType(myType); var dynamicList = Activator.CreateInstance(listType); ((IList)dynamicList).Add(fooContent); 

Para invocar dinamicamente o Markdown(IEnumerable contents)

 new Encoder().Markdown( (dynamic) dynamicList) 

Observe o uso de dynamic na chamada do método. No tempo de execução dynamicList será List (além disso também sendo IEnumerable ), pois mesmo o uso da dinâmica ainda está enraizado em uma linguagem fortemente tipada, o fichário de tempo de execução selecionará o método Markdown apropriado. Se não houver correspondências de tipo exato, ele procurará um método de parâmetro de object e, se nenhum deles corresponder a uma exceção de fichário de tempo de execução, será alertado de que nenhum método corresponde.

A desvantagem óbvia para essa abordagem é uma enorme perda de segurança de tipo em tempo de compilation. No entanto, o código ao longo destas linhas permitirá que você opere em um sentido muito dynamic, que em tempo de execução ainda é totalmente typescript como você espera que seja.