2012-01-05 5 views
1

私は単純なクラスを持っています。そして私はをいくつかの方法とプロパティに条件を追加する必要があります。たとえば:アスペクトの文字列条件をコンパイルする方法

public class Example 
{ 
    public Boolean Condition {get; set;} 
    public Double ConditionValue {get; set;} 

    [Verify("!Condition && ConditionValue>5")] 
    public void DoSomthing() 
    { ... } 
} 

私はアスペクト属性に条件(例えば、 "!> 5条件& & ConditionValue")を確認したいです。属性にアクション/関数を与えることができないので、単純な文字列を与えます。この文字列を条件に変換する必要があります。

[Serializable] 
public class MyAspectAttribute : OnMethodBoundaryAspect 
{ 
    public override void OnExit(MethodExecutionArgs args) 
    { 
     if (!this.Condition && this.ConditionValue>5) // If-statment from string, this is the problem... 
     { ... } 
    } 
} 

文字列から実際のif-statmentをどのように抽出できますか?私はいくつかの解決策を見ていますが、私は彼らが大丈夫かどうかはわかりません:

  1. ランタイムコンパイラを使用してください。 CSharpCodeProvider。
  2. などのライブラリを使用するhttp://flee.codeplex.com/
  3. 他に何か...?

どのように正常に処理できますか?ありがとう!

UPD:私はアドバイスに疑問... UPD2を編集した:

public class Example2 
    { 
     public Boolean Condition {get; set;} 

     [LoggingIf("Condition")] 
     public void DoSomthing1() 
     { ... } 

     [PrintReportIf("!Condition")] 
     public void DoSomthing2() 
     { ... } 
    } 
+0

この場合カスタム属性はなぜですか? –

+0

私はクラスメンバーにいくつかのロジックを追加しようとします。それは作品ですが、私は良い解決策を探しています...そして、私は、属性を持たない多くの(!)プロパティとメソッドにいくつかのロジックを追加できますか? – xtmq

+1

属性内でコードを呼び出すと、あなたはどのようなコードを呼び出すでしょうか?アトリビュートは、飾るメンバについては何も知らず、アトリビュートを呼び出すものもありません。メタデータはメタデータのみを指定します。 –

答えて

3

lambda expressions parserを使用していますか?

[Verify("(Example e) => !e.Condition && e.Condition > 5")] 
public void DoSomthing() 
{ ... } 

そして使用して、その後にコンパイルします:あなたが線に沿って何かを行うことができるはず

[Serializable] 
public class MyAspectAttribute : OnMethodBoundaryAspect 
{ 
    public override void OnExit(MethodExecutionArgs args) 
    { 
     ExprParser parser = new ExprParser(); 
     LambdaExpression lambda = parser.Parse(/* Verify string comes here */); 
     bool isConditionMet = (bool) parser.Run(lambda, this); 

     if (isConditionMet) 
     { ... } 
    } 
} 

編集:

をカスタム・ユーザー・タイプの場合、あなたは(名前空間を提供する必要がありますアセンブリが、パーサから呼び出されるものとは異なるアセンブリに存在する場合):

ExprParser.Using.Add("PersonTypeNamespace"); 
ExprParser parser = new ExprParser(); 
LambdaExpression lambda = parser.Parse("(Person p) => p.Name"); 
var output = parser.Run(lambda, new Person { Name = "DragonFire" }); 

download sectionユーザーガイドファイル - ライブラリの使用に関するいくつかの追加情報を提供します。

+1

ラムダパーサーにとって+1ですが、私はまだ彼が条件のために魔法の弦を避けるべきだと思います。 –

+0

はい、これは私が探していたものです!ありがとう!! – xtmq

+0

私はそれを使用しようとするが、私は例外があります:あなたが名前空間/アセンブリ名を追加する必要があります - チェック:私は、「(E)=> e.Condition」文字列... – xtmq

-1

は、なぜこのような何かをやっていない:私は私のコードを検証しない試みを行う、私はこれを行うことができます:

public class Example 
{ 
    public Boolean Condition {get; set;} 
    public Double ConditionValue {get; set;} 


    public void DoSomthing() 
    { 
      Verify.That(!Condition && ConditionValue>5); 
      ... 
    } 
} 

それはほとんど同じコードの量だ、あなたが、設定で物事を置くことができるプライベートメンバーを確認し、複雑な検証を行います、コンパイル時にコンパイルされ、検証されます。

+0

)=私は主題が条件をコンパイルされ、postsharpは加算のみであると考え...しかし、私は一度私の質問を編集します。 –

+0

しかし、彼はすでに文字列に条件を書きました。 – ivowiblo

+1

あなたは正しいです、そして、それは彼がやろうとしていることに関する多くの問題の一つです。 –

-1

デバッグを困難にする1つの手法は、#defineの値を使用することです。今

#define CONDITION_5 

、以下の例のクラスでは、DoSomething()が表示されている:

例えば、いくつかの他のプロジェクトでは、あなたはCONDITION_5のように宣言することができます。あなたのコードのためにこれらのする変数が必要な場合は

public class Example 
{ 

#if CONDITION_5 
    public void DoSomthing() 
    { ... } 
#endif 
} 

、あなたはあなたの選択を保存するために別のクラスにパブリック変数を定義することができます。

public static class Global { 
    public static bool Condition_5 = true; 
} 

さて、以下の例のクラスでは、DoSomething()は常にあります表示されますが、値を設定しないかぎり実行されるものはありません。

public class Example 
{ 

    public void DoSomthing() 
    { 
    if (Global.Condition_5) 
    { 
     // do stuff 
    } 
    } 
} 

あなたのように、私はより洗練された方法を見たいと思います。

編集:私は私の最初のコメントに留意よう

ザ・OPは、彼の元の質問を変更しました。私の答えは、元の質問に適していたが、マークされた答えを与えられた質問ではなかった。

+0

[OK]を、それを自動化されていません。それはあなたが探しているものではないかもしれませんが、私はここに少し残しておきます。 – jp2code

+0

??? #if CONDITION_5はコンパイル時に実行されるもので、そのメソッドは決して存在しません(または常に存在します)。意味がない。 – ivowiblo

+0

私は私の質問を編集して、私の問題を指定している... – xtmq

1

ブール論理を実装する一連のオブジェクトを作成します。

  • は、コンパレータを等しいより大きいコンパレータ(プロパティと値の名前を取ります)
  • とコンパレータ(2個のコンパレータを取る)
  • ブール
  • (プロパティと値の名前を取ります)評価者は、(ブール型プロパティの名前を取る)
  • など、など

次に、あなたの属性をパラメータとして、これらのオブジェクトの1つを取る持っている

[Verify(new AndComparator(
    new BooleanEvaluator ("Condition"), 
    new GreaterThanComparator("ConditionValue", 5)))] 
public void DoSomthing() 
+0

は、私は、これを行うことはできません:あなたは、あなただけのようなものが必要でき – xtmq

+0

@DragonFire確かに[(「CurrentInfo.User.Account.IsValid」)を確認してください] [Springの式の評価]( http://www.springframework.net/doc-latest/reference/html/expressions.html);つまり、あなたが行っているように文字列*反射*を歩きます。また、クールなユーザー名。 –

0

は、コードコントラクトを見てみましょう:http://research.microsoft.com/en-us/projects/contracts/カスタム属性を持つことは必須ではない場合、彼らはあなたが探しているだけで何かもしれません。

(それは本当にIDEが遅くなりますが、とにも時間をコンパイル)コード契約がpermissableパラメータに制約を定義するのが得意であり、メソッドの値を返すと、必要に応じて、実行時にそれらをチェック

+0

私は契約について知っていますが、私の仕事はソフトウェア検証にリンクしていません... – xtmq

0

あなたはすでに式を知っていますあなたは単にアスペクトの値を渡すだけで使いたいです。

public class MyValidationAspect : OnMethodBoundaryAspect 
{ 

public int Val1 { get; set; } 
public int Val2 { get; set; } 

public override void OnExit(MethodExecutionArgs args) 
    { 
     if (this.args.Arguments[0] > Val1) // If-statment from string, this is the problem... 
     { ... } 
    } 


} 

[MyValidationAspect(Val1 = 5, Val2 = ...)] 

具体的なアスペクトのセットを作成し、必要に応じて値を渡すだけで汎用/動的になるようにしないでください。

または、Rosylen(サービスとしてのコンパイラ)を使用することができます。

+0

私は別の複雑な条件を使用しなければなりません...しかし、Rosylen ...それは非常に面白いです!! – xtmq

+0

@DragonFire複数のアスペクトを作成します。それをダイナミックにしようとすると、問題は発生しません。条件が動的に変わるユースケースは私には見えません。あなたはそれを間違っているか、怠け者であることを非常に懸念しています。 –

関連する問題