2011-08-23 38 views
8

Uygulamamda daha önce bir yöntemi "ek açıklama" yapmak için normal C# öznitelikleri kullandım. Örn .:Tek bir yöntemde birden çok yönü

 

[Foo(SomeKey="A", SomeValue="3")] 
[Foo(SomeKey="B", SomeValue="4")] 
public void TheMethod() 
{ 
    SpecialAttributeLogicHere(); 
} 

 

Ne SpecialAttributeLogicHere() yaptım düşünceli bu özel yöntemi açıklamalı tüm Foo özellikten bakmak oldu. O zaman (kendi başına), tüm anahtarlar ve değerler için kendi sözlüğünü oluşturur.

Şu anda PostSharp'a geçmeye çalışıyorum, çünkü SpecialAttributeLogic, OnEntry içinde bir özelliğe (ve daha temiz olan yöntem gövdesinden kaldırılmış) yerleştirilebilir. Foo, OnMethodBoundaryAspect'i genişleten bir yönüyle değiştirilecektir.


[Foo(SomeKey="A", SomeValue="3")] 
[Foo(SomeKey="B", SomeValue="4")] 

Ama Foo bir OnEntry, varsa "SpecialAttributeLogic" İki kez idam edilecek anlamına gelir:

Hala bunu şu şekilde kullanmak istiyorum. Temel olarak, her bir Foo() 'dan bütün anahtarları ve değerleri bir mantığa uygulayacağım bir sözlüke "topladım".

Bu (veya en iyi uygulamalar) PostSharp ile nasıl yapılır? Teşekkürler!

+0

cevabım altında çalışma örneğim eklendi. –

cevap

2

Yöntemin içinde bir namevaluepair oluşturmak istediğiniz gibi görünüyor. Bunu bir yönüyle yapamazsın. Önerdiğim bir MethodInterceptionAspect kullanmak ve yöntemdeki özniteliklerini yansıtmak, sonra koleksiyonunuzu oluşturmak ve bir parametresi (belki de aşırı yüklenmiş bir yöntem kullanarak) veya bir sınıf üyesi olarak ayarlamak yöntemine iletmek.

Performansı en iyi şekilde tutmak için değerleri derleme zamanında yansıtabilirsiniz.

Sorunuz için hızlı bir çözüm. Bu biraz çirkin (uyum sağlamak için değişiklikler yapmanız gerekecek). Başka yollar var ama onlar "jenerik" değiller.

namespace ConsoleApplication12 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyExampleClass ec = new MyExampleClass(); 
      ec.MyMethod(); 
     } 
    } 

    public class MyExampleClass 
    { 
     [Special(Key = "test1", Value = "1234")] 
     [Special(Key = "test2", Value = "4567")] 
     [MyAspect] 
     public void MyMethod() 
     { 
      MyMethod(new Dictionary<string, string>()); 
     } 

     public void MyMethod(Dictionary<string, string> values) 
     { 
      //Do work 
     } 

    } 

    [Serializable] 
    public class MyAspect : MethodInterceptionAspect 
    { 
     Dictionary<string, string> values = new Dictionary<string, string>(); 
     MethodInfo target; 

     public override void CompileTimeInitialize(System.Reflection.MethodBase method, AspectInfo aspectInfo) 
     { 
      target = method.DeclaringType.GetMethod(method.Name, new Type[] { typeof(Dictionary<string, string>) }); 

      foreach (Attribute a in method.GetCustomAttributes(false)) 
      { 
       if (a is SpecialAttribute) 
       { 
        values.Add(((SpecialAttribute)a).Key, ((SpecialAttribute)a).Value); 
       } 
      } 
     } 

     public override void OnInvoke(MethodInterceptionArgs args) 
     { 
      if (values == null || values.Count < 1) 
      { 
       args.Proceed(); 
      } 
      else 
      { 
       target.Invoke(args.Instance, new object[] { values }); 
      } 

     } 
    } 
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true) ] 
    public class SpecialAttribute : Attribute 
    { 
     public string Key { get; set; } 
     public string Value { get; set; } 
    } 
} 

hedef ve değerleri, her iki çalışma zamanında tüketimi için (çalışma zamanı olan) compiletime işlevine başlamaktadır. Onlar derleme zamanında yönü ile serileştirilir. Bu sayede çalışma zamanında yansıma isabetinden tasarruf edersiniz.

+0

İyi cevap. Alternatif olarak, aynı yaklaşımı yapabileceğimi, ancak MethodInterceptionAspect yerine OnMethodBoundaryAspect'i kullanabileceğimi varsayalım. Sonra, OnEntry'de yansıma kullanarak yöntemin özelliklerini okurdum. Ama öte yandan, belki de MethodInterceptionAspect ihtiyaçlarım için daha iyidir. Bunu biraz düşünmeliyim ... –

+1

Evet, bunu yapabilirsiniz, ancak özniteliklerden birini tıkladığınızda sorun verilere erişiyor. Özniteliği bir yönlendirme yapmazdım, çünkü kodunuzu yürütmek ve gerçekten karmaşıklaştırmak için birden çok özelliğe sahip olursunuz. Ancak MethodBoundaryAspect kullanarak bir yöntem aşırı yüklenme ihtiyacını önler. Yani her iki şekilde de iyi olmalı. –

0

Sadece bir not olarak, MethodInterceptionAspect kullanarak bitti ve sadece OnInvoke'u geçersiz kıldım. OnInvoke içinde ben ayarladım tüm System.Attributes (yani DustinDavis 'örnekte SpecialAttribute) veren args.Method.GetCustomAttributes() baktı.

Bu öznitelikler ve özelliklerini kullanarak, çalıştırmak için gereken mantığı çalıştırabilirim. Mantık başarılı olursa, ben bir özel durum atmazsa, args.Proceed() ile bitiriyorum.

İlgili konular