На самом деле есть 4 различных способа вызова использования. Приведенные ниже примеры и цифры примерно соответствуют вашим номерам, за исключением того, что я добавил # 4 ...
using (var a = File.CreateText(@"c:\temp\test.txt")) //#1
{
// a is only visible in this context
}
TextWriter w;
using(w = File.CreateText(@"c:\temp\test.txt")) //#2
{
// w is visible outside of this context, but is only valid within the context
}
w = File.CreateText(@"c:\temp\test.txt");
using (w) //#3
{
// w is visible outside of this context, but is only valid between assignment and end of this context
}
using (File.CreateText(@"c:\temp\test.txt")) //#4
{
// the disposable is not visible in any context
}
Я бы порекомендовал вам взглянуть на метод Expression.CatchBlock (...) и посмотреть, как ему передаются параметры. Оператор catch аналогичен в том, что объявлена локальная переменная для использования внутри инструкции. Это может означать, что ваша UsingBoilerPlate может выглядеть примерно так ...
public static Expression<Action> UsingBoilerPlate(
Expression disposeExpression,
Expression bodyExpression,
ParameterExpression localVariable,
bool unbound) { ... }
public static Expression<Action> UsingBoilerPlate(
Expression disposeExpression,
Expression bodyExpression,
ParameterExpression localVariable)
{ return UsingBoilerPlate(disposeExpression, bodyExpression, localVariable, true); }
public static Expression<Action> UsingBoilerPlate(
Expression disposeExpression,
Expression bodyExpression)
{ return UsingBoilerPlate(disposeExpression, bodyExpression, null); }
Чтобы справиться с каждым из 4 сценариев, вы бы назвали это так ...
var action1 =
Expression.Lambda<Action>
(
Using
(
disposableExpression,
bodyExpression,
localVariable
)
);
action1.Compile()();
var action2 =
Expression.Lambda<Action>
(
Expression.Block
(
new [] { localVariable },
new Expression[] {
Using
(
disposableExpression,
bodyExpression,
localVariable,
false
),
Expression.IfThenElse(
Expression.NotEqual(
localVariable, Expression.Constant(null)),
((Expression<Action>)(() => Console.WriteLine("w is NOT null"))).Body,
((Expression<Action>)(() => Console.WriteLine("w is null"))).Body
)
}
)
);
action2.Compile()();
В следующем примере используется маленькая хитрость, где using(w)
эквивалентно using(w = w)
var action3 =
Expression.Lambda<Action>
(
Expression.Block
(
new [] { localVariable },
new Expression[] {
Expression.Assign(localVariable, disposeExpression);
Using
(
localVariable,
bodyExpression,
localVariable,
false
),
Expression.IfThenElse(
Expression.NotEqual(
localVariable, Expression.Constant(null)),
((Expression<Action>)(() => Console.WriteLine("w is NOT null"))).Body,
((Expression<Action>)(() => Console.WriteLine("w is null"))).Body
)
}
)
);
action3.Compile()();
И последнее,
var action4 =
Expression.Lambda<Action>
(
Using
(
disposableExpression,
bodyExpression
)
);
action4.Compile()();
Таким образом, вы не можете понять, связано ли выражение ParameterExpression с внешним вашим методом, но вы можете сказать своему методу, является ли он или нет.