Fala filhotes, tudo bem? A pouco tempo atrás fiz um post sobre o Simple.Data, que usava o tipo Dynamic do .net 4.0. Como não tinha nenhum artigo aqui no 100loop vamos ao primeiro.
Funcionamento
O tipo dynamic permite que suas operações sejam resolvidas apenas em tempo de execução e não em tempo de compilação. Podendo acessar qualquer operação de qualquer tipo de objeto ( semelhante ao reflection) apenas invocando a operação.
– “Como assim?”
Vamos dizer que nossa classe Turma só tem uma propriedade Codigo. Se eu tentasse fazer isso:
Iria me mandar esse erro:
_100LoopProject.Classes.Turma’ does not contain a definition for ‘Nome’ and no extension method ‘Nome’ accepting a first argument of type ‘_100LoopProject.Classes.Turma’ could be found (are you missing a using directive or an assembly reference?)
Afinal não existe essa propriedade. Mas se eu fizesse usando o dynamic:
dynamic turma = new Turma(); turma.Codigo = 1; turma.Nome = "Turma 1";
Não daria erro nenhum, ja que o compilador “ignora” o dynamic, mas quando a aplicação executar essa linha e ver que “Nome” não existe, ai sim, vai gerar uma exceção. Entendeu? O dynamic funciona igual a um object mas suas operações não são resolvidas e nem conferidas pelo compilador.
Dynamic Language Runtime
O Dynamic Language Runtime (DLR) é uma nova API presente no framework 4.0 e adiciona uma série de serviços para linguagens dinâmicas ao CLR. É ela que permite o uso do tipo dynamic no C# e das linguagens dinâmicas como o IronPython e o IronRuby.
Arquitetura do DLR
A conversão do tipo dynamic em tempo de execução
Mas então, como minha aplicação vê esse tipo dynamic? Bom, na verdade é o seguinte: Quando o dynamic é compilado ele vira um object.
“Wait, what?”
Um exemplo fica mais fácil de entender. Vou criar um objeto dynamic, setar diversos valores e verificar qual o seu tipo em tempo de execução:
// Criamos o nosso objeto Dynamic dynamic objDyn; objDyn = 3; //Retona System.Int32 Console.WriteLine(objDyn.GetType()); objDyn = "andre"; //Retona System.String Console.WriteLine(objDyn.GetType()); objDyn = new Usuario(); //Retona ProjetoTeste.ConsoleTest.Usuario Console.WriteLine(objDyn.GetType()); Console.ReadLine();
Entedeu? Por isso pode se dizer que o Tipo dynamic só existe em tempo de compilação, ja que depois disso o próprio compilador analisa e grava as informações das operações alem de converter o cabloco dinamico para um tipo object.
Sim, filhotes. Com o reflection você consegue fazer tudo isso, mas com algumas diferenças, vamos la:
// Pega o tipo do objeto var tp = typeof(Turma); // Cria uma instancia da turma var objTurma = Activator.CreateInstance(tp); // Usando Reflexion: Setando uma propriedade tp.GetProperty("Codigo").SetValue(objTurma, 1, null); // Chamo o método passando uma string como parametro tp.InvokeMember("GetDescription", BindingFlags.InvokeMethod, null, objTurma, new object[] { "Super turma de teste" });
E agora com o Dynamic:
// Pega o tipo do objeto var tp = typeof(Turma); // Cria uma instancia da turma dynamic objTurma = Activator.CreateInstance(tp); // Usando Dynamic: Setando uma propriedade objTurma.Codigo = 1; // Chamo o método passando uma string como parametro objTurma.GetDescription("Super turma de teste");
Bang! 1×0 para o Dynamic
Então com o Dynamic nós os tratamos com o objetos normais, só chamamos o metodo/propriedade com seus valores/parâmetros e pronto! Bom, então o dynamic é mais facil, mas e a performace?
Opa mas é ai que as coisas mudam de figuras!… NOT!
Fazendo um programinha de testes:
public static void Main(string[] args) { var nTimes = 1000000; var value = "Hello World"; var myTestType = new MyTestType(); DateTime start, end; var property = typeof(MyTestType).GetProperty("MyDynamicProperty"); start = DateTime.Now; // Setando a propriedade via reflection for (var i = 0; i < nTimes; i++) { //var property = typeof(MyTestType).GetProperty("MyDynamicProperty"); property.SetValue(myTestType, value, null); } end = DateTime.Now; Console.WriteLine(end.Subtract(start).ToString()); dynamic myTestType2 = new MyTestType(); start = DateTime.Now; // Setando a propriedade via dynamic for (int i = 0; i < nTimes; i++) { myTestType2.MyDynamicProperty = value; } end = DateTime.Now; Console.WriteLine(end.Subtract(start).ToString()); // Setando a propriedade normalmente var myTestType3 = new MyTestType(); start = DateTime.Now; for (int i = 0; i < nTimes; i++) { myTestType3.MyDynamicProperty = value; } end = DateTime.Now; Console.WriteLine(end.Subtract(start).ToString()); Console.ReadLine(); } } public class MyTestType { public string MyDynamicProperty { get; set; } }
Reflection: 00:00:01.7481000
Dynamic: 00:00:00.1080062
Normal: 00:00:00.0110006
Percebe-se que o Dynamic também é bem mais rapido do que o Reflection.
– “Nú! Então já posso migrar tudo para Dynamic!?”
Extamente! Não. Bom nem tudo nessa vida é tão simples assim...
Não existe nenhuma mágica
A maior vantagem do dynamic é também sua maior desvantagem. Lembra mais acima que eu falei que o compilador transforma ele em um tipo object? Então como ele pode acessar uma propriedade de um tipo desconhecido?
Usando reflection.
– Mas perai se o dynamic tambem usa reflection porque ele é mais rapido?
Quando o compilador o transforma para um tipo object ele também cria um cache com as informações necessarias para acessar as propriedades de forma mais rapida. Qual a desvantagem disso? A primeira operação demora mais e perde um pouco da memória para manter o cache, tudo isso em troca de operações (bem) mais rapidas do que o reflection.
Conclusão
O dynamic é fantástico, mas como o reflection ele deve ser usado com cuidado, você não vai querer sobrecarregar o seu servidor atoa. E apesar de ter inumeras vantagens em cima do reflection analise bastante qual dos dois é melhor para sua aplicação, uma boa dica é dar uma olhada nesse tópico no Stack Overflow: http://stackoverflow.com/questions/4646786/dynamic-lang-runtime-vs-reflection.
Bom filhotes, então é isso pretendo fazer mais um post sobre dynamic semana que vem, ate mais.
Referências
http://lucisferre.net/2011/01/18/being-dynamically-typed-in-a-statically-typed-world/
http://www.codeproject.com/KB/cs/dynamicincsharp.aspx
http://www.amazedsaint.com/2010/03/c-40-dynamic-keyword-for-dummies-under.html
http://msdn.microsoft.com/en-us/library/dd264741.aspx
http://msdn.microsoft.com/en-us/library/dd264736.aspx
http://msdn.microsoft.com/en-us/library/dd233052.aspx
http://blog.wekeroad.com/2010/08/09/csharps-new-clothes
http://stackoverflow.com/questions/4646786/dynamic-lang-runtime-vs-reflection