2013-09-17 5 views
1

Скажем, у меня есть следующий C# код: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 раз в секунду в течение нескольких часов, поэтому он должен быть быстрым и легким в памяти.

+0

Это, вероятно, будет быстрее, если вы отделенный каждое поле и не требует разбора, например .: 'вар PropertyName = "PropertyX"; var subPropertyName = "Id"; var val = "y"; '. Кроме того, возможно, вам потребуется снизить ваши ожидания относительно скорости .. в зависимости от ваших точных требований. –

+2

Как 'var val' становится' y' из выражения? –

+1

Возможно, вам захочется ознакомиться с некоторыми предложениями в [этом сообщении] (http://social.msdn.microsoft.com/Forums/en-US/31ac96da-415e-424b-9e1f-6aec86c4c3ae/how-to-convert- string-in-systemlinqexpressionsexpression-in-c) –

ответ

2

У вас возникнут проблемы с этим 30 раз в секунду в течение нескольких часов. Каждый компилятор создаст другую сборку в памяти, и нет возможности выгрузить загруженную сборку без разрыва домена приложения. Таким образом, ваш объем памяти будет расти без ограничений.

Если вы хотите предотвратить использование неограниченной памяти, вам необходимо скомпилировать и загрузить сборку в отдельном домене приложения. Затем вы можете снести этот домен приложения, чтобы выгрузить загруженную сборку.

Но создание нового домена приложения, сборка сборки и разрывание домена приложения 30 раз в секунду? Возможно, я полагаю. Возможно, вы могли бы создать домен приложения и загрузить сборки в него в течение минуты, а затем снести этот домен приложения и создать новый. Это, по крайней мере, ограничит использование вашей памяти, а также сократит обработку. Но я не знаю, какой размер мог занимать 1800 загрузочных сборок.

Вам определенно нужно поэкспериментировать с пространством имен System.CodeDom. Я подозреваю, что вы слишком много задаете. Комментарий, рекомендующий интерпретируемый язык, может быть способом пойти. Это очень сложно сказать без дополнительной информации о вашем приложении.

1

Не полный ответ, но его можно использовать в качестве отправной точки, если вы не найдете что-то лучшее или более полное.

Попробуйте сделать это простой и легкий, используя код, как это:

public static object GetPropValue(object src, string propName) 
{ 
    return src.GetType().GetProperty(propName).GetValue(src, null); 
} 

Get property value from string using reflection in C#

2

Лучше всего было бы использовать выражения для построения действий, скомпилировать его и кэш его. Ниже приведен упрощенный пример, иллюстрирующий, как это сделать. В этом случае я занимаюсь только одним уровнем в графе свойств.

/// <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") ; 
Смежные вопросы