2010-04-17 9 views
0

J'ai un aspect qui implémente INotifyPropertyChanged sur une classe. L'aspect comprend les éléments suivants:PostSharp lors de l'utilisation de DataContractSerializer?

[OnLocationSetValueAdvice, MethodPointcut("SelectProperties")] 
    public void OnPropertySet(LocationInterceptionArgs args) 
    { 
     var currentValue = args.GetCurrentValue(); 
     bool alreadyEqual = (currentValue == args.Value); 

     // Call the setter 
     args.ProceedSetValue(); 

     // Invoke method OnPropertyChanged (ours, the base one, or the overridden one). 
     if (!alreadyEqual) 
      OnPropertyChangedMethod.Invoke(args.Location.Name); 
    } 

Cela fonctionne bien quand j'instancier la classe normalement, mais je rencontre des problèmes quand je désérialiser la classe en utilisant une DataContractSerializer. Cela contourne le constructeur, ce qui, je suppose, interfère avec la façon dont PostSharp s'installe. Cela finit par provoquer une exception NullReferenceException dans un ensemble de propriétés interceptées, mais avant qu'il ait appelé le OnPropertySet personnalisé, je suppose qu'il interfère avec la configuration de LocationInterceptionArgs.

Est-ce que quelqu'un d'autre a rencontré ce problème? Y a-t-il un moyen de contourner ce problème?


j'ai fait quelques recherches et découvert que je peux résoudre le problème en faisant ceci:

[OnDeserializing] 
    private void OnDeserializing(StreamingContext context) 
    { 
     AspectUtilities.InitializeCurrentAspects(); 
    } 

Je pensais que, d'accord, ce n'est pas trop mal, alors j'ai essayé de le faire dans mon Aspect:

private IEnumerable<MethodInfo> SelectDeserializing(Type type) 
    { 
     return 
      type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).Where(
       t => t.IsDefined(typeof (OnDeserializingAttribute), false)); 
    } 

    [OnMethodEntryAdvice, MethodPointcut("SelectDeserializing")] 
    public void OnMethodEntry(MethodExecutionArgs args) 
    { 
     AspectUtilities.InitializeCurrentAspects(); 
    } 

Malheureusement, même si elle intercepte la méthode correctement, il ne fonctionne pas. Je pense que l'appel à InitializeCurrentAspects ne se transforme pas correctement, car il est maintenant dans l'aspect plutôt que directement dans la classe améliorée. Y a-t-il un moyen de l'automatiser proprement pour ne pas avoir à m'inquiéter de l'appeler dans toutes les classes que je veux avoir l'Aspect?

Répondre