2009-04-03 2 views
12

나는 그것으로 전달 된 액션 위임을 기반으로 "계정"개체를 변경하는 방법이 있습니다(lambda expression) 문자열을 Action 대리자로 파싱하는 쉬운 방법이 있습니까?

public static void AlterAccount(string AccountID, Action<Account> AccountAction) { 
    Account someAccount = accountRepository.GetAccount(AccountID); 
    AccountAction.Invoke(someAccount); 
    someAccount.Save(); 
} 

을이 작품 의도 한대로 ...

AlterAccount("Account1234", a => a.Enabled = false); 

...하지만 지금은 내가 '시도 좋아하고 어떻게이 같은 방법이있다 D :

public static void AlterAccount(string AccountID, string AccountActionText) { 
    Account someAccount = accountRepository.GetAccount(AccountID); 
    Action<Account> AccountAction = MagicLibrary.ConvertMagically<Action<Account>>(AccountActionText); 
    AccountAction.Invoke(someAccount); 
    someAccount.Save(); 
} 

그 다음처럼 사용할 수 있습니다 :

,
AlterAccount("Account1234", "a => a.Enabled = false"); 

계정 "Account1234"를 사용하지 않도록 설정하십시오.

linq dynamic query library을 보았습니다. Func 타입 델리게이트에 대해 더 많이 또는 적게하는 것처럼 보였습니다. 그리고 표현식 트리에 대한 지식은 무엇을 달성 할 수 있을지를 생각해 내기에 충분하지 않습니다. 내가 원하는.

내가 원하는 것을 쉽게 할 수있는 방법이 있습니까? 아니면 표현을 올바르게 배우고 코드를로드해야합니까?

(나는이 작업을 수행 할 수있는 이유는 사용자가 변경을 수행하는 람다 식을 지정할 수있는 PowerShell 스크립트에서 대량 업데이트 계정 개체의 쉬운 방법을 허용하는 것입니다.)

+0

하드 방법 System.Reflection.Emit.DynamicMethod를 사용하여 IL 코드를 생성하는 것입니다. 그러나이 경우 속성 이름과 값을 지정하고 반사 기반 속성 설정자를 사용하는 구문을 허용하는 것이 더 쉽습니다. – eulerfx

+0

네, 생각했습니다.하지만 AlterAccount ("Account1234", "a => a.Enabled =! a.Enabled")를 호출 할 수있는 것과 같이 잠재적으로 강력한 것들을 배제 할 것이라고 생각합니다. (왜 그렇게 구체적으로하고 싶은지 확실하지 않지만 다른 더 합리적인 예가있다) – Whisk

+2

'MagicLibrary.ConvertMagically' –

답변

1

더 일반적인 방법은 없습니다 람다식이 람다 식 외부에서 정의 된 것을 참조 할 수 있기 때문에 전체 컴파일없이 문자열을 람다 식으로 구문 분석 할 수 있습니다. 네가 원하는 특별한 사건을 다루는 도서관이 없다는 것을 안다. C# 토론 그룹의 thread에 대한 자세한 설명이 있습니다.

원하는 것을 얻는 가장 쉬운 방법은 런타임에 메서드를 컴파일하는 것입니다. "a.Enabled = true; return a;"라는 문자열을 사용하는 함수를 작성할 수 있습니다. 계정을 매개 변수로 사용하는 함수의 중간에이를 고수합니다. 이 library을 시작점으로 사용하지만 another thread에서 언급 한 기능을 사용할 수도 있습니다.

+0

고마워 - 빠른 평가에서 평가할 때 작동하지 않는 것 같아요. 액션 대리인에게 "a => a.Enabled = true"와 같은 문자열 - 내가 잘못한 일을하고 있습니까? 그렇지 않습니다. 자체적으로 완전한 C# 문이 아니기 때문에 작동하지 않습니까? 내가 명확하게 질문을 업데이 트했습니다. – Whisk

+0

rossfabricant; 그가 언급하는 동적 linq 라이브러리는 정확히 그렇게합니다. 물론 컴파일 할 때 타이핑 정보를 제공해야하지만 잘 컴파일됩니다. – MichaelGG

+0

쿼리를 작성할 수는 있지만 상태를 수정하는 모든 것을 빌드 할 수는 없습니다. – RossFabricant

3

동적 LINQ 라이브러리는 경량 방식으로 코드를 컴파일 할 수있는 식을 생성하므로 좋은 선택입니다.

제공 한 예제는 실제로 부울을 생성합니다. 따라서 Func을 요청할 수 있어야하며이를 정렬 할 수 있어야합니다.

편집 : 표현식에는 할당이 전혀 없기 때문에 물론 틀립니다.

다른 잠재적 인 방법은 두 개의 람다를 사용하는 것입니다. 하나는 당신이 원하는 속성을 찾기 위해, 하나는 값을 제공합니다 :

(A => a.AccountId)

(A => TRUE)

그런 다음 첫 번째 람다와에서 참조하는 속성을 설정하는 반사를 사용 두 번째 결과. Hackish이지만 C# 컴파일러를 호출하는 것과 비교하면 여전히 가벼운 편입니다.

이 방법을 사용하면 코드 젬을 많이 할 필요가 없습니다. 사용자가 얻는 표현에는 필요한 모든 것을 포함 할 것입니다.쉽게

+0

내 생각 엔 ... "a => a.Enabled == false"를 수행하면 작동하지만, "a => a.Enabled = false"를하고있는 중입니다. 계정 때문에 일부 수정 없이는 작동하지 않을 것이라고 생각합니다. – Whisk

+0

바 맞습니다. 그것은 funcs를 위해 작동합니다 : Func exp =() => test = false; 식을 표현할 수는 없지만 표현을 표현할 방법이 없습니다. – MichaelGG

+0

넵 - 동적 LINQ 작업을 동작 및 Func 과 함께 사용하도록 수정하는 경로를 따라갈 수도 있다고 생각합니다. – Whisk

0

:

  • 사용 CodeDom는 "주변 클래스"는 표현을 구축하는 데 사용할 수 있습니다를 포함하는 모듈을 생성하기 위해; 이 클래스는 응용 프로그램에 알려진 인터페이스를 구현해야합니다.
  • CodeSnippedExpression을 사용하여 표현식을 해당 멤버에 삽입합니다.
  • 런타임에이 클래스의 인스턴스를 만들려면 Activator 유형을 사용하십시오.

기본적으로, 당신은 된 CodeDom 다음과 같은 클래스를 구축해야합니다 :이 작업을 수행하는 경우

public IHasAccountAction { 
    public Action<Account> AccountAction { get; } 
} 

, 당신이 표현은 문자열에서 컴파일받을 수 있습니다

using System; 
using MyNamespace1; 
using ... 
using MyNamespace[N]; 

namespace MyNamespace.GeneratedTypes 
{ 
    public class ExpressionContainer[M] : IHasAccountAction 
    { 
    public Action<Account> AccountAction { 
     get { 
     return [CodeSnippedExpression must be used here]; 
     } 
    } 
    } 
} 

IHasAccountAction이라고 가정하면 쉽게. 표현식 트리 표현이 필요한 경우 생성 유형에 Action<Account> 대신 Expression<Action<Account>>을 사용하십시오.

+0

(일반 연산자에 대한 귀하의 의견에 대답, btw) –

3

이 작업을 시도 할 수 있습니다 : Dynamic Lambda Expressions Using An Isolated AppDomain

그것은 CodeDOM을 컴파일러를 사용하여 람다 식을 컴파일합니다. 생성 된 메모리 내장 어셈블리를 처리하기 위해 컴파일러는 격리 된 AppDomain에서 실행됩니다. 도메인 경계를 통해 표현식을 전달하려면 직렬화되어야합니다. 아아, Expression<>Serializable이 아닙니다. 따라서 트릭을 사용해야합니다. 모든 세부 사항은 게시물에 설명되어 있습니다.

저는 그 구성 요소의 저자입니다. 당신의 의견을 듣고 싶습니다.

1

당신은 약간 다를 수 있습니다 Spring.NET의 lambda expression evaluation engine

표현을 사용할 수 있습니다,하지만 여전히 당신은 표현을위한 문자열을 사용합니다.