Pergunta

Eu posso fazer um eval("something()"); para executar o código dinamicamente em JavaScript.Existe uma maneira para eu fazer a mesma coisa em C#?

Um exemplo do que eu estou tentando fazer é:Eu tenho uma variável de número inteiro (dizer i) e eu tenho vários propriedades pelos nomes:"Propriedade1", "Property2", "Propriedade3", etc.Agora, eu quero realizar algumas operações nos " Propriedadeeu "propriedade, dependendo do valor do i.

Isso é realmente simples com Javascript.Existe alguma maneira de fazer isso com C#?

Foi útil?

Solução

Infelizmente, C# não é uma linguagem dinâmica como essa.

O que você pode fazer, no entanto, é a criação de um código fonte em C# arquivo completo com classe e tudo mais, e executá-lo através da CodeDom fornecedor para C# e compilá-lo em um assembly e, em seguida, executá-lo.

Este post no fórum do MSDN contém uma resposta com algum código de exemplo a página para baixo um pouco:
criar um método anônimo a partir de uma string?

Eu poderia dizer que esta é uma solução muito boa, mas é possível de qualquer maneira.

Que tipo de código que você vai esperar, em que seqüência?Se for um menor subconjunto de código válido, por exemplo, apenas as expressões matemáticas, pode ser que outras alternativas não existe.


Editar:Bem, que me ensina a ler as perguntas completamente em primeiro lugar.Sim, a reflexão seria capaz de dar-lhe alguma ajuda aqui.

Se você dividir a seqüência de caracteres por ;primeiro, para obter propriedades individuais, você pode usar o código a seguir para obter um PropertyInfo objeto para uma determinada propriedade de uma classe e, em seguida, usar esse objeto para manipular um objeto em particular.

String propName = "Text";
PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);

Link: PropertyInfo.Método SetValue

Outras dicas

Usando o Roslyn API de scripting (mais amostras aqui):

// add NuGet package 'Microsoft.CodeAnalysis.Scripting'
using Microsoft.CodeAnalysis.CSharp.Scripting;

await CSharpScript.EvaluateAsync("System.Math.Pow(2, 4)") // returns 16

Você também pode executar qualquer pedaço de código:

var script = await CSharpScript.RunAsync(@"
                class MyClass
                { 
                    public void Print() => System.Console.WriteLine(1);
                }")

De referência e o código que foi gerado em execuções anteriores:

await script.ContinueWithAsync("new MyClass().Print();");

Não realmente.Você pode usar a reflexão para conseguir o que você quer, mas não vai ser tão simples como no Javascript.Por exemplo, se você deseja definir o campo particular de um objeto para alguma coisa, você pode usar esta função:

protected static void SetField(object o, string fieldName, object value)
{
   FieldInfo field = o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
   field.SetValue(o, value);
}

Esta é uma função eval em c#.Eu é usado para converter funções anônimas (Expressões Lambda) a partir de uma seqüência de caracteres.Fonte: http://www.codeproject.com/KB/cs/evalcscode.aspx

public static object Eval(string sCSCode) {

  CSharpCodeProvider c = new CSharpCodeProvider();
  ICodeCompiler icc = c.CreateCompiler();
  CompilerParameters cp = new CompilerParameters();

  cp.ReferencedAssemblies.Add("system.dll");
  cp.ReferencedAssemblies.Add("system.xml.dll");
  cp.ReferencedAssemblies.Add("system.data.dll");
  cp.ReferencedAssemblies.Add("system.windows.forms.dll");
  cp.ReferencedAssemblies.Add("system.drawing.dll");

  cp.CompilerOptions = "/t:library";
  cp.GenerateInMemory = true;

  StringBuilder sb = new StringBuilder("");
  sb.Append("using System;\n" );
  sb.Append("using System.Xml;\n");
  sb.Append("using System.Data;\n");
  sb.Append("using System.Data.SqlClient;\n");
  sb.Append("using System.Windows.Forms;\n");
  sb.Append("using System.Drawing;\n");

  sb.Append("namespace CSCodeEvaler{ \n");
  sb.Append("public class CSCodeEvaler{ \n");
  sb.Append("public object EvalCode(){\n");
  sb.Append("return "+sCSCode+"; \n");
  sb.Append("} \n");
  sb.Append("} \n");
  sb.Append("}\n");

  CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
  if( cr.Errors.Count > 0 ){
      MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText, 
         "Error evaluating cs code", MessageBoxButtons.OK, 
         MessageBoxIcon.Error );
      return null;
  }

  System.Reflection.Assembly a = cr.CompiledAssembly;
  object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");

  Type t = o.GetType();
  MethodInfo mi = t.GetMethod("EvalCode");

  object s = mi.Invoke(o, null);
  return s;

}

Eu tenho escrito um projeto de código aberto, Dinâmica Expresso, que pode converter expressão de texto escrito com um C# sintaxe em delegados (ou árvore de expressão).Expressões são analisados e transformados em Árvores De Expressão sem o uso de compilação ou de reflexão.

Você pode escrever algo como:

var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");

ou

var interpreter = new Interpreter()
                      .SetVariable("service", new ServiceExample());

string expression = "x > 4 ? service.SomeMethod() : service.AnotherMethod()";

Lambda parsedExpression = interpreter.Parse(expression, 
                          new Parameter("x", typeof(int)));

parsedExpression.Invoke(5);

Meu trabalho é baseado em Scott Gu artigo http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

Todos que iria trabalhar.Pessoalmente, para que determinado problema, eu provavelmente seria um pouco diferente abordagem.Talvez algo como isto:

class MyClass {
  public Point point1, point2, point3;

  private Point[] points;

  public MyClass() {
    //...
    this.points = new Point[] {point1, point2, point3};
  }

  public void DoSomethingWith(int i) {
    Point target = this.points[i+1];
    // do stuff to target
  }
}

Quando utilizar padrões como este, você tem que ter cuidado para que os seus dados são armazenados por referência e não por valor.Em outras palavras, não faça isso com primitivos.Você tem que usar sua grande inchado de classe correspondentes.

Eu percebi que não é exatamente a questão, mas a questão tem sido muito bem atendida e eu pensei que talvez uma abordagem alternativa que pode ajudar.

Eu não, agora se você quer executar C# instruções, mas você já pode executar instruções de Javascript em C# 2.0.O código-fonte aberto da biblioteca Jint é capaz de fazê-lo.É um interpretador Javascript para .LÍQUIDA.Passar um programa em Javascript e ele será executado dentro do seu aplicativo.Você pode até mesmo passar C# objecto como argumentos e fazer a automação sobre ele.

Também se você quiser apenas para avaliar a expressão de suas propriedades, dar uma chance para NCalc.

Você pode usar a reflexão para obter a propriedade e invocá-lo.Algo como isto:

object result = theObject.GetType().GetProperty("Property" + i).GetValue(theObject, null);

Isto é, supondo que o objeto que tem a propriedade é chamada de "theObject" :)

Você também pode implementar um Webbrowser e, em seguida, carregar um arquivo html que contém o javascript.

Em seguida, u ir para o document.InvokeScript Método para este navegador.O Valor de retorno da função eval pode ser apanhado e convertidos em tudo o que você precisa.

Eu fiz isso em vários Projetos e funciona perfeitamente.

Espero que ajude

Você poderia fazê-lo com um protótipo de função:

void something(int i, string P1) {
    something(i, P1, String.Empty);
}

void something(int i, string P1, string P2) {
    something(i, P1, P2, String.Empty);
}

void something(int i, string P1, string P2, string P3) {
    something(i, P1, P2, P3, String.Empty);
}

e assim por diante...

Usa a reflexão para analisar e avaliar uma expressão de vinculação de dados contra um objeto em tempo de execução.

DataBinder.Método Eval

Eu tenho escrito um pacote, SharpByte.Dinâmica, para simplificar a tarefa de compilar e executar o código dinamicamente.O código pode ser chamado em qualquer objeto de contexto usando métodos de extensão, conforme detalhado mais aqui.

Por exemplo,

someObject.Evaluate<int>("6 / {{{0}}}", 3))

retorna 3;

someObject.Evaluate("this.ToString()"))

retorna o contexto do objeto de representação de seqüência de caracteres;

someObject.Execute(@
"Console.WriteLine(""Hello, world!"");
Console.WriteLine(""This demonstrates running a simple script"");
");

executa as instruções de um script, etc.

Arquivos executáveis podem ser obtidos facilmente usando um método de fábrica, como visto no exemplo aqui--tudo o que você precisa é o código-fonte e lista de espera-parâmetros nomeados (tokens são incorporados usando o triplo-suporte de notação, como {{{0}}}, para evitar colisões com cadeia.Format (), bem como Guidão-como sintaxes):

IExecutable executable = ExecutableFactory.Default.GetExecutable(executableType, sourceCode, parameterNames, addedNamespaces);

Cada executável (objeto de script ou expressão) é thread-safe, que podem ser armazenados e reutilizados, suporta o registo de dentro de um script, armazena informações de tempo e última exceção, se encontrado, etc.Há também um método Copy() compilado em cada um para permitir a criação de cópias baratas, i.é.usando um objeto executável compilado a partir de um script ou expressão como um modelo para a criação de outros.

A sobrecarga de executar um script compilado ou instrução é relativamente baixa, em bem menos de um microssegundo em hardware modesto, e já scripts compilados e expressões são armazenados em cache para reutilização.

Eu estava tentando obter um valor de uma estrutura (classe) membro por seu nome.A estrutura não foi dinâmico.Todas as respostas não funcionou, até que eu finalmente consegui-lo:

public static object GetPropertyValue(object instance, string memberName)
{
    return instance.GetType().GetField(memberName).GetValue(instance);
}

Este método irá retornar o valor do membro por seu nome.Ele funciona em estrutura regular (classe).

Você pode verificar a Heleonix.Reflexão a biblioteca.Ela fornece métodos para obter/ajustar/chamar membros dinamicamente, incluindo membros aninhados, ou se um membro é claramente definidos, você pode criar um getter/setter (lambda compilado em um delegado, que é mais rápido do que a reflexão:

var success = Reflector.Set(instance, null, $"Property{i}", value);

Ou se o número de propriedades não é infinita, você pode gerar setters e chache-los (setters são mais rápidos, pois eles são compilados delegados):

var setter = Reflector.CreateSetter<object, object>($"Property{i}", typeof(type which contains "Property"+i));
setter(instance, value);

Setters pode ser do tipo Action<object, object> mas os casos podem ser diferentes em tempo de execução, de modo que você pode criar listas de setters.

Infelizmente, o C# não tem qualquer nativo comodidades para fazer exatamente o que você está pedindo.

No entanto, o meu C# eval, o programa não permite a avaliação de código C#.Ele fornece para a avaliação de código C# em tempo de execução e suporte para muitos C# instruções.Na verdade, esse código é utilizável dentro de qualquer um .LÍQUIDO do projeto, no entanto, é limitado à utilização de C# sintaxe.Dê uma olhada no meu site, http://csharp-eval.com, para obter mais detalhes.

a resposta correta é que você precisa armazenar todo o resultado para manter a mem0ry o baixo uso.

um exemplo seria como este

TypeOf(Evaluate)
{
"1+1":2;
"1+2":3;
"1+3":5;
....
"2-5":-3;
"0+0":1
} 

e adicionar a uma Lista

List<string> results = new List<string>();
for() results.Add(result);

guardar o id e o código de

espero que isso ajude

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top