2010-03-19 11 views
4

Il y a quelques mois, j'ai découvert PostSharp, et pendant un certain temps, c'était bon.Est-ce que Spring.Net peut fonctionner comme PostSharp?

Mais alors juridique est revenu avec une réponse disant qu'ils n'aiment pas la licence des anciennes versions. Ensuite, le ministère m'a dit que le prix de la 2.0 était trop élevé (pour le nombre de sièges dont nous avions besoin) ... J'étais extrêmement déçu, mais pas découragé. Je ne peux pas être le seul cadre de ce genre, pensais-je.

j'ai gardé la recherche d'un remplacement, mais la plupart était soit mort, mal entretenu (en particulier dans le département de documentation), pour une utilisation académique, ou tout ce qui précède (je vous regarde Aspect.Net)

Puis j'ai découvert Spring.Net, et pendant un temps, c'était bon.

J'ai lu la documentation et j'ai continué à peindre ce qui semblait être une image supplémentaire d'un nirvana AOP. Je n'étais plus verrouillé aux attributs pour marquer où je voulais que l'interception de code ait lieu, mais il pouvait être configuré en XML et les modifications ne nécessitaient pas de re-compilation. Génial.

Je regardai les échantillons et vu ce qui suit, dans chaque scénario d'utilisation unique:

// Create AOP proxy using Spring.NET IoC container. 
IApplicationContext ctx = ContextRegistry.GetContext(); 
ICommand command = (ICommand)ctx["myServiceCommand"];  
command.Execute(); 
if (command.IsUndoCapable) 
{ 
    command.UnExecute(); 
} 

Pourquoi les deux premières lignes de code doit exister? Ça gâche tout. Cela signifie que je ne peux pas simplement fournir à un utilisateur un ensemble d'aspects et d'attributs ou de config XML qu'ils peuvent utiliser en collant des attributs appropriés sur les méthodes/classes/etc appropriées ou en modifiant le motif de correspondance en XML. Ils doivent modifier leur logique de programme pour que cela fonctionne!

Existe-t-il un moyen de faire en sorte que Spring.Net se comporte comme PostSharp dans ce cas? (par exemple, l'utilisateur n'a besoin que d'ajouter des attributs/config XML, pas de modifier le contenu des méthodes.)

Sinon, existe-t-il une alternative valable et fonctionnelle à PostSharp? J'ai vu quelques questions intitulées comme ça sur SO, mais aucune d'entre eux cherchaient en fait à remplacer PostSharp, ils voulaient seulement compléter sa fonctionnalité.J'ai besoin de remplacement complet

+0

La réponse courte est non, car PostSharp réécrit réellement votre code en tant qu'étape post-construction. Je vais laisser les experts du printemps peser, cependant; Je sais que vous pouvez être très proche si vous utilisez DI pour instancier vos services et êtes prêt à essayer l'interception de méthodes. – Aaronaught

+0

Enfer, je suis tout pour réécrire! Je ferais même ce qui est nécessaire moi-même. Si seulement CCI-AST était suffisamment bien documenté, ou du moins son code était fonctionnel et suffisamment diversifié? _> Y a-t-il autre chose qui puisse répondre à mes besoins? –

+0

Peut-être que vous pouvez être plus précis sur ce que vous essayez de faire et où vous avez trouvé cet exemple? Je ne suis pas très au printemps, comme je l'ai déjà mentionné, mais je l'ai évalué une fois et je ne me souviens pas d'avoir à intégrer un de ces trucs ICommand dans les classes pour utiliser le système Advice. – Aaronaught

Répondre

9

En bref, oui, Spring.Net AOP peut fonctionner de la façon dont vous décrivez en utilisant la configuration XML: vous faites pas besoin d'utiliser ces deux premières lignes de code, en fait la configuration basée sur le code est déconseillée.Vous pouvez configurer Spring.Net AOP en utilisant uniquement la configuration basée sur XML et c'est en fait l'approche recommandée

Il y a plusieurs étapes à ceci:

  1. Créez vos conseils: BeforeAdvice, AroundAdvice, AfterReturningAdvice et ThrowsAdvice sont les types de conseils pris en charge. AroundAdvice utilise l'interface AOPAlliance, les autres utilisent les interfaces Spring.AOP.
  2. Définir vos points d'action
  3. Appliquer les points d'action et des conseils

Exemple de configuration (généralisée à partir d'une configuration en direct):

<!-- START Spring.Net AOP --> 

    <object id="beforeAdvice" type="MyBeforeAdvice, MyAOP"></object> 
    <object id="beforeAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"> 
    <property name="Advice" ref="beforeAdvice" /> 
    </object> 

    <object id="returnsAdvice" type="MyAfterReturningAdvice, MyAOP"></object> 
    <object id="returnsAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"> 
    <property name="Advice" ref="returnsAdvice" /> 
    </object> 

    <object id="throwsAdvice" type="MyThrowsAdvice, MyAOP"></object> 
    <object id="throwsAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop"> 
    <property name="Advice" ref="throwsAdvice" /> 
    </object> 


    <!-- Advise objects --> 
    <object type="Spring.Aop.Framework.AutoProxy.ObjectNameAutoProxyCreator, Spring.Aop"> 
    <property name="ObjectNames"> 
     <list> 
     <value>*Command</value> 
     <value>...</value> 
     </list> 
    </property> 
    <property name="InterceptorNames"> 
     <list> 
     <value>beforeAdvisor</value> 
     <value>returnsAdvisor</value> 
     <value>throwsAdvisor</value> 
     </list> 
    </property> 
    </object> 


    <!-- END Spring.Net AOP --> 

Le tissage est réalisé à l'exécution et est assez rapide et non intrusive.

Espérons que cela est d'usage,

Andrew

+0

Un billet de blog avec une brève introduction à l'AOP en général: http://andrewlocatelliwoodcock.com/2011/05/02/brief- intro-à-aop / – Alfamale

2

Je pense que vous êtes à la recherche de la fonction lookup-method injection.

Vous avez chargé le contexte de l'application Spring.NET quelque part au début. La dépendance basée sur le code sur Spring.NET est minimale. Le problème est que partout où vous avez besoin d'un (conseillé) service, vous dépendez explicitement Spring.NET avec ContextRegistry.GetContext() ..

Vous pouvez travailler autour de cette méthode avec remplacement à l'aide recherche méthode, par exemple :

Créer un AbstractCommandFactory:

namespace MyNamespace { 
    public abstract class AbstractCommandFactory : ICommandFactory { 
    public abstract ICommand getMyCommand(); 
    } 
} 

en utilisant Spring.NET vous pouvez getMyCommand retourner un objet Spring.NET:

<objects> 
    <object id="commandfactory" 
      type="MyNamespace.AbstractCommandFactory, MyAssembly"> 
    <lookup-method name="getMyCommand" object="commands.mycommand" /> 
    </object> 

    <object id="commands.mycommand" 
      type=MyNamespace.MyCommandImplementation, MyAssembly" /> 
</objects> 

Lorsque vous initialisez le contexte d'application Spring.NET, chargez cette commande en usine et transmettez la référence. Lorsque vous avez besoin d'une instance de MyCommandImplementation, vous demandez juste un de l'instance d'usine:

public void doSomeWork() { 
    // factory is an ICommandFactory 
    // instantiated earlier using the explicit context.getObject("commandfactory") 
    ICommand myCommand = this.factory.getMyCommand(); 
    myCommand.Execute(); 
} 

Maintenant, votre dépendance explicite sur Spring.NET est très minime: seulement à la charge initiale + instanciation de vos usines. Le reste de votre code reste propre. Points bonus: vous pouvez créer plus facilement des mocks ICommandFactory/ICommand pour tester votre code.