Domanda

mi è stato chiesto di realizzare delega castello dinamica nella mia applicazione web asp.net e stavo attraversando paio di articoli che ho ricevuto da Castello Progetto e Codice progetto su delega castello dinamica asp NET web ....

Entrambi gli articoli delt con la creazione di intercettori, ma non riesco a ottenere l'idea perché intercettori vengono utilizzate con le classi .... Perché dovrei intercettare la mia classe, che si sta comportando correttamente?

È stato utile?

Soluzione

diciamo di lasciare che la classe ha bisogno di fare 3 cose per una determinata operazione:

  1. Eseguire un controllo di sicurezza;
  2. Registrazione della chiamata di metodo;
  3. Cache il risultato.

Diamo inoltre supporre che la classe non sa nulla del specifica modo che avete configurato la vostra sicurezza, la registrazione o la memorizzazione nella cache. Hai bisogno di dipendere da astrazioni di queste cose.

Ci sono alcuni modi per andare su di esso. Un modo potrebbe essere quello di istituire un gruppo di interfacce e iniettabile Uso costruttore:

public class OrderService : IOrderService
{
    private readonly IAuthorizationService auth;
    private readonly ILogger logger;
    private readonly ICache cache;

    public OrderService(IAuthorizationService auth, ILogger logger,
        ICache cache)
    {
        if (auth == null)
            throw new ArgumentNullException("auth");
        if (logger == null)
            throw new ArgumentNullException("logger");
        if (cache == null)
            throw new ArgumentNullException("cache");
        this.auth = auth;
        this.logger = logger;
        this.cache = cache;
    }

    public Order GetOrder(int orderID)
    {
        auth.AssertPermission("GetOrder");
        logger.LogInfo("GetOrder:{0}", orderID);
        string cacheKey = string.Format("GetOrder-{0}", orderID);
        if (cache.Contains(cacheKey))
            return (Order)cache[cacheKey];
        Order order = LookupOrderInDatabase(orderID);
        cache[cacheKey] = order;
        return order;
    }
}

Questo non è il codice orribile, ma pensare ai problemi che stiamo introducendo:

  • La classe OrderService non può funzionare senza tutte e tre le dipendenze. Se vogliamo fare in modo che può, dobbiamo cominciare infarcendo il codice con controlli nulli ovunque.

  • Stiamo scrivendo un ton di codice aggiuntivo per eseguire un'operazione relativamente semplice (guardando un ordine).

  • Tutto questo codice standard deve essere ripetuto in tutti metodo, rendendo per un grande brutto, implementazione, soggetto ad errori.

Ecco una classe che è molto più facile da mantenere:

public class OrderService : IOrderService
{
    [Authorize]
    [Log]
    [Cache("GetOrder-{0}")]
    public virtual Order GetOrder(int orderID)
    {
        return LookupOrderInDatabase(orderID);
    }
}

Aspect Oriented Programming , questi attributi sono chiamati Partecipa Punti , la serie completa di cui è chiamato un Point Cut .

Invece di scrivere codice in realtà la dipendenza, più e più volte, lasciamo "suggerimenti" che alcune operazioni aggiuntive dovrebbero essere eseguiti per questo metodo.

Naturalmente, questi attributi devono arrivare trasformato in codice qualche tempo , ma si può rinviare che tutta la strada fino al codice dell'applicazione principale, mediante la creazione di un delega per la OrderService (nota che il metodo GetOrder è stato fatto virtual perché deve essere sostituito per il servizio), e intercettazione il metodo GetOrder.

La scrittura del intercettore potrebbe essere semplice come questo:

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        if (Attribute.IsDefined(invocation.Method, typeof(LogAttribute))
        {
            Console.Writeline("Method called: "+ invocation.Method.Name);
        }
        invocation.Proceed();
    }
}

E creare il proxy potrebbe essere:

var generator = new ProxyGenerator();
var orderService = (IOrderService)generator.CreateClassProxy(typeof(OrderService),
    new LoggingInterceptor());

Questo non è solo un sacco di codice meno ripetitivo, ma si rimuove completamente la dipendenza reale , perché guardare quello che abbiamo fatto - non abbiamo nemmeno sono un autorizzazione o sistema di caching ancora, ma il sistema funziona ancora. Possiamo solo inserto la logica di autorizzazione e la cache in seguito registrando un altro intercettore e controllo per AuthorizeAttribute o CacheAttribute.

Speriamo che questo spiega il "perché".

Barra laterale: commenti Come Krzysztof Kozmic, non è un DP "best practice" per usare un intercettore dinamica come questo. Nel codice di produzione, non si vuole avere l'intercettore in esecuzione per i metodi non necessari, in modo da utilizzare un IInterceptorSelector .

Altri suggerimenti

Il motivo si usa Castello-DynamicProxy è per quello che è chiamato Aspect programmazione orientata. Esso consente di interject codice nel flusso normale funzionamento del codice, senza la necessità di diventare dipendente dal codice stesso.

Un semplice esempio è come sempre, la registrazione. Che si creerebbe un DynamicProxy attorno a una classe che si dispone di errori da che registra i dati che vanno nel metodo e cattura tutte le eccezioni e quindi registra l'eccezione.

Uso della intercepter il codice corrente non ha alcuna idea esiste (ammesso che abbiate il software incorporato in un modo disaccoppiato con le interfacce correttamente) ed è possibile modificare la registrazione delle classi con un'inversione del contenitore di controlli di utilizzare la classe Proxied invece senza dover cambiare una sola riga altrove nel codice. Poi, quando si risolve il bug è possibile disattivare il proxy.

Utilizzo più avanzate di proxy può essere visto con NHibernate in cui tutto il lazy loading è gestita attraverso i proxy.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top