C# 思维弯曲器:在运行时将字符串编译为赋值表达式
本文关键字:字符串 编译 表达式 赋值 运行时 弯曲 | 更新日期: 2023-09-27 18:31:36
>假设我有以下 C# 代码:
//build an object
var mynewObj = new Thing();
//build an assignment value
var val = "abc";
var memberExpression = "x.PropertyX.Id = y";
[? some stuff happens ?]
Assert.IsTrue(myNewObj.PropertyX.Id == "abc");
memberExpression 是某个数据库中的值。我想获取这些部分,构建一个表达式,然后编译/执行它。我需要每秒执行此操作~30次,持续数小时,因此它必须快速且轻便的内存。
最好的办法是使用表达式来构建一个动作,编译它并缓存它。 下面是一个稍微简化的示例,说明了如何执行此操作。 在这种情况下,我只在属性图的深处做一个级别。
/// <summary>
/// Build a lambda expression for a setter
/// </summary>
public static Action<T, U> GetSetter<T, U>(string propertyName)
{
// TODO: Maintain a dictionary mapping typeof(T)+property onto the
// resulting Action so this can be cached
PropertyInfo property = typeof(T).GetProperty(propertyName);
var setMethod = property.GetSetMethod();
var parameterT = Expression.Parameter(typeof(T), "x");
var parameterU = Expression.Parameter(typeof(U), "y");
var newExpression =
Expression.Lambda<Action<T, U>>(
Expression.Call(parameterT, setMethod, parameterU),
parameterT,
parameterU
);
return newExpression.Compile();
}
使用它:-
//build an object
var mynewObj = new Thing();
//build an assignment value
var val = "abc";
var propertyName = "PropertyX";
var setter = GetSetter<Thing, string>(propertyName);
// Execute the cached setter (it's really fast!)
setter(mynewObj, val);
Debug.Assert(mynewObj.PropertyX == "abc") ;
您将无法在数小时内每秒执行此操作 30 次。每次编译都会创建一个不同的内存中程序集,并且无法在不拆除应用程序域的情况下卸载加载的程序集。因此,您的内存占用量将无限增长。
如果要防止无限使用内存,则必须在单独的应用程序域中编译和加载程序集。然后,可以拆除该应用程序域以卸载加载的程序集。
但是,创建新的应用程序域、编译程序集以及每秒 30 次拆除应用程序域?我想有可能。也许您可以创建一个应用程序域并将程序集加载到其中一分钟,然后拆除该应用程序域并创建一个新应用程序域。这至少会在一定程度上限制您的内存使用,并减少处理。但我不知道 1,800 个加载的组件会有什么样的足迹。
您绝对需要试验System.CodeDom
命名空间。不过,我怀疑你的要求有点太多了。推荐解释性语言的评论可能是要走的路。如果没有有关您的应用程序的更多信息,真的很难说。
不是一个完整的答案,但可以作为一个起点,如果你没有找到更好或更完整的东西。
尝试使它变得简单,并使用如下代码进行轻量级:
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
在 C# 中使用反射从字符串中获取属性值