Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 内联计算代码(或使用反射)_C#_Reflection_Codedom - Fatal编程技术网

C# 内联计算代码(或使用反射)

C# 内联计算代码(或使用反射),c#,reflection,codedom,C#,Reflection,Codedom,我对这一点进行了大量简化,以了解问题的核心: 我有一个需要填充属性的控件。不幸的是,这些值都位于CodeDom.codedStatements中 因此,我必须使用如下代码来搜索值: static string GenerateCode(CodeStatementCollection statements, Control control) { var writer = new StringWriter(); var compiler = new

我对这一点进行了大量简化,以了解问题的核心:

我有一个需要填充属性的控件。不幸的是,这些值都位于CodeDom.codedStatements中

因此,我必须使用如下代码来搜索值:

static string GenerateCode(CodeStatementCollection statements, Control control)
      {
         var writer = new StringWriter();

         var compiler = new CSharpCodeProvider();

         foreach (CodeStatement statement in statements)
         {
            var codeAssignStatement = statement as System.CodeDom.CodeAssignStatement;

            var left = codeAssignStatement?.Left as System.CodeDom.CodePropertyReferenceExpression;

            if (left == null)
            {
               continue;
            }

            var right = codeAssignStatement.Right as System.CodeDom.CodeObjectCreateExpression;

            if (right == null)
            {
               continue;
            }

            var expressionWriter = new StringWriter();
            compiler.GenerateCodeFromExpression(right,expressionWriter,null);
            var expression = expressionWriter.ToString();

            control.SetPropertyValue(left.PropertyName, expression);

            compiler.GenerateCodeFromStatement(statement, writer, null);

         }

         return writer.ToString();
      }
请注意,代码使用的是反射,SetPropertyValue实际上是一个扩展方法:

public static void SetPropertyValue(this object obj, string propName, object value)
      {
         obj.GetType().GetProperty(propName).SetValue(obj, value, null);
      }
但这仅在值是文本值而不是表达式时有效

在运行时,我从CodeDom语句中得到的是一个表达式,控件也是一个按钮

按钮位置=新系统图纸点(12,12)

因此,在上面的代码示例中,expression=“New System.Drawing.Point(12,12)”

现在,我不想先运行一系列IF语句来确定类型

是否可以使用反射基于表达式设置属性


如果没有,是否可以在.net中使用某种类型的Eval函数来实现这一点?

要从脚本中创建代码,需要动态编译该方法

您必须做的第一件事是将该方法编译成
MethodInfo
。 您可以创建一个方法来实现这一点

public static MethodInfo CreateMethodInfo(string script, string className, string methodName)
{
    using (var compiler = new CSharpCodeProvider())
    {
        var parms = new CompilerParameters
        {
            GenerateExecutable = false,
            GenerateInMemory = true,
            ReferencedAssemblies = { "System.Drawing.dll" }
        };
        return compiler.CompileAssemblyFromSource(parms, script)
            .CompiledAssembly.GetType(className)
            .GetMethod(methodName);
    }
}
一旦你这样做了,你可以像这样使用它

var script = "public class Methods{public static System.Drawing.Point DoSomething(){return new System.Drawing.Point(12, 12);}}";

var method = CreateMethodInfo(script, "Methods", "DoSomething");
既然
method
变量保存了
MethodInfo
,那么您只需要调用它

Button.Location = (Point)method.Invoke(null, null);

我想你可以试试LINQ表达式。

将您的方法更改为如下所示:

public static void SetPropertyValue(this object obj, string propName, Expression<Func<T, object>> value)
publicstaticvoid SetPropertyValue(此对象对象对象,字符串propName,表达式值)

在表达式中配置和编译委托函数,并在SetPropertyValue()中调用它。

你真聪明!这很有效。非常感谢你!