Func을 <문자열, 부울> 식 트리에 사용하기 위해 bool로하는
각 노드에 소요 내가 지나치게 복잡한 이진 표현 트리 빌딩 시스템을 가지고
트리는 문자열, 플레이어 및 세계를 취하는 외부 함수를 나타내며 bool (테스트 용) 문자열 (출력용) 또는 void (작업 용)를 반환합니다.
내 문제는 세 가지입니다. 첫째로 나는 Expression.Condition
또는 Expression.IfThenElse
과 같은 것을 사용하려면 시험 표현식이 Expresson<bool>
이 아닌 Expression<func<string, Player, World, bool>>
(Expression.And
가 출력 됨)
두 번째로 Player와 World의 메모리 참조가 동일하게 유지되어야합니다. 트리의 노드 중 하나가 Player 내에서 무언가를 업데이트하는 경우 다음과 같이 업데이트됩니다. 다음 노드.
마지막으로 나는 모든 문자열을 하나씩 추가해야합니다. 열심히 나무를 코딩 할 수 있다면
,이 같은 뭔가를 찾고 끝낼 수 있습니다 :
class Main
{
string Foo(string text, World world, Player player)
{
string output;
output += SomeClass.PrintStarting();
if (SomeClass.Exists(text, world, player))
{
output += SomeClass.PrintName(text, world, player);
SomeClass.KillPlayer(text, world, player);
if (SomeClass.Exists(text, world, player))
output += SomeClass.PrintSurvived(text, world, player);
}
else
output += SomeClass.PrintNotExists(text, world, player);
return output;
}
}
public class SomeClass
{
string PrintStart(string text, World world, Player player)
{
return "Starting.\n";
}
bool Exists(string text, World world, Player player)
{
player.Lives;
}
string PrintName(string text, World world, Player player)
{
return player.Name + ".\n";
}
string PrintSurvived(string text, World world, Player player)
{
return player.Name + "died.\n";
}
string PrintNotExists(string text, World world, Player player)
{
return "This person does not exist.\n";
}
void KillPlayer(string text, World world, Player player)
{
if (text != "kidding")
player.Lives = false;
}
}
더 정교하게하려면 나는 그것의 시험/지정/문자열의 모든 메소드와 SomeClass의 인스턴스를 가지고있다. 그런 다음 Expression<func<string[], World, Player, bool>>
, Expression<Action<string[], World, Player>>
및 Expression<func<string[], World, Player, string>>
의 목록을 만들고이를 함께 트리에 넣기 시작합니다. 내가 (예를 들어) 나를 떠나 처리 한 어떤 일이 일어나는지의 실제 순서 :
public string Foo2(string text, World world, Player player)
{
ParameterExpression result = Expression.Parameter(typeof(string), "result");
ParameterExpression inputString = Expression.Parameter(typeof(string[]), "inputString");
ParameterExpression inputWorld = Expression.Parameter(typeof(World), "inputWorld");
ParameterExpression inputPlayer = Expression.Parameter(typeof(Player), "inputPlayer");
System.Reflection.MethodInfo methodInfo = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
Expression textPrintStarting = (Expression<Func<string, World, Player, string>>)((Text, World, Player) => SomeClass.PrintStarting(Text, World, Player));
Expression testExists = (Expression<Func<string, World, Player, bool>>)((Text, World, Player) => SomeClass.Exists(Text, World, Player));
Expression textPrintName = (Expression<Func<string, World, Player, string>>)((Text, World, Player) => SomeClass.PrintName(Text, World, Player));
Expression killPlayer = (Expression<Action<string, World, Player>>)((Text, World, Player) => SomeClass.KillPlayer(Text, World, Player));
Expression textPrintSurvived = (Expression<Func<string, World, Player, string>>)((Text, World, Player) => SomeClass.PrintSurvived(Text, World, Player));
Expression textPrintNotExist = (Expression<Func<string, World, Player, string>>)((Text, World, Player) => SomeClass.PrintNotExists(Text, World, Player));
Expression innerTest =
Expression.Condition(
Expression.Invoke(Expression.Lambda<Func<string, World, Player, bool>>(testExists, inputString, inputWorld, inputPlayer)),
Expression.Assign(result, Expression.Call(methodInfo, result, Expression.Lambda<Func<string, World, Player, string>>(textPrintSurvived, inputString, inputWorld, inputPlayer))),
Expression.Empty());
Expression success =
Expression.Block(
Expression.Assign(result, Expression.Call(methodInfo, result, Expression.Lambda<Func<string, World, Player, string>>(textPrintName, inputString, inputWorld, inputPlayer))),
Expression.Lambda<Action<string, World, Player>>(killPlayer, inputString, inputWorld, inputPlayer),
innerTest);
Expression failure =
Expression.Assign(result, Expression.Call(methodInfo, result, Expression.Lambda<Func<string, World, Player, string>>(textPrintNotExist, inputString, inputWorld, inputPlayer)));
Expression outerTest =
Expression.Condition(
Expression.Invoke(Expression.Lambda<Func<string, World, Player, bool>>(testExists, inputString, inputWorld, inputPlayer)),
success,
failure);
Expression finalExpression =
Expression.Block(
Expression.Assign(result, Expression.Call(methodInfo, result, Expression.Lambda<Func<string, World, Player, string>>(textPrintStarting, inputString, inputWorld, inputPlayer))),
outerTest);
return Expression.Lambda<Func<string, World, Player, string>>(
Expression.Block(new[] { result },
finalExpression)).Compile()(text, world, player);
}
문제는이 bool로하는 Func을 변환 할 수 없기 때문에 오류를 던져 Condition
문에 있습니다. 매개 변수가 전달되는지 여부도 확실하지 않습니다. (디버그 할 수 없었기 때문에)
당신은 자세히 설명해 주시겠습니까? 당신의 문제에서 당신이 말하는 말이 나에게 의미가 없습니다. 당신은 무엇을 가지고 있습니까? (구체적인 예를 들어주십시오)? 그리고 무엇을하고 싶습니까 (다시, 구체적으로 기재하십시오)?어떤 표현이 있고 그것을 어떻게 사용 하시겠습니까? –
문제점의 현재 구현에 대한 추가 세부 사항을 추가했습니다. – bigjokerfish
모든 것을 표현식으로 사용하려는 특별한 이유가 있습니까? 나는 그것을 전혀 필요가 없다. 표현식의 예제가 필요하고 실제로 가능한지 확인하려면 함수를 람다 식으로 저장할 수 있습니다. –