Frage

Ich wurde gebeten, Burg dynamischen Proxy in meiner asp.net Web-Anwendung zu implementieren, und ich ging durch einige Artikel, die ich erhalte von Code Project über Schloss dynamische Proxy in asp .net Web-Anwendung ....

Beide Artikel delt mit Abfangraketen zu schaffen, aber ich kann nicht auf die Idee kommen, warum Abfangjäger mit Klassen verwendet werden .... Warum sollte ich meine Klasse abfangen, die richtig verhält?

War es hilfreich?

Lösung

Lassen Sie uns sagen, dass Ihre Klasse benötigt 3 Dinge für eine bestimmte Operation zu tun:

  1. Führen Sie eine Sicherheitsüberprüfung;
  2. Melden Sie sich der Aufruf der Methode;
  3. Cache das Ergebnis.

Nehmen wir weiter an, dass Ihre Klasse wissen nichts über die spezifische So können Sie Ihre Sicherheit, Protokollierung oder Caching konfiguriert haben. Sie müssen sich auf Abstraktionen von diesen Dingen abhängen.

Es gibt ein paar Möglichkeiten, um darüber zu gehen. Eine Möglichkeit wäre, eine Reihe von Schnittstellen einzurichten und zu verwenden Konstruktor Injektion:

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;
    }
}

Dies ist nicht schrecklich Code, aber denken Sie an den Problemen, die wir Einführung:

  • Die OrderService Klasse kann funktionieren nicht ohne alle drei Abhängigkeiten. Wenn wir wollen es so können sie, müssen wir überall mit null Kontrollen Würzen den Code starten.

  • Wir schreiben einen ton zusätzlichen Code eine relativ einfache Operation auszuführen (aufzublicken einen Auftrag).

  • diese vorformulierten Der gesamte Code hat in wiederholt werden alle Methode, was für eine sehr große, hässliche, Bug-anfällig Umsetzung.

Hier ist eine Klasse, die viel leichter zu pflegen:

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

Aspect Oriented Programming werden diese Attribute genannt Join Punkte , der vollständige Satz von denen genannt Punkt Cut .

Statt der Abhängigkeit Code tatsächlich zu schreiben, immer und immer wieder, lassen wir „Hinweise“, dass einige zusätzliche Operationen sollen für dieses Verfahren durchgeführt werden.

Natürlich haben diese Attribute in den Code bekommen gedreht irgendwann , aber Sie können verschieben, dass den ganzen Weg bis zu Ihrem Haupt-Anwendungscode, durch die Schaffung eines Proxy für die OrderService (man beachte, dass die GetOrder Methode virtual gemacht wurde, weil es für den Dienst außer Kraft gesetzt werden muss), und Abfangvorrichtung die GetOrder Methode.

die Abfangjäger Schreiben so einfach wie das sein könnte:

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();
    }
}

Und die Proxy-Erstellung wäre:

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

Das ist nicht nur viel weniger sich wiederholende Code, aber es vollständig entfernt die tatsächliche Abhängigkeit , weil Blick, was wir getan haben - wir nicht einmal wurde ein Genehmigung oder Caching-System noch nicht, aber das System noch läuft. Wir können nur Einsatz der Genehmigung und Caching-Logik später durch eine andere Abfangjäger Registrierung und für AuthorizeAttribute oder CacheAttribute zu überprüfen.

Hoffentlich erklärt dies die "warum."

Seitenleiste: Wie Krzysztof Kozmic Kommentare, es ist kein DP "best practice" einen dynamischen Abfangjäger wie diese zu verwenden. In Produktionscode, wollen Sie nicht die Abfangjäger für unnötige Methoden ausgeführt haben, so verwenden, um eine IInterceptorSelector statt.

Andere Tipps

Der Grund, warum Sie Castle-Dynamic verwenden würden, ist für das, was Aspect Orientierte Programmierung genannt. Es lässt Sie einwerfen Code in das Standardbetriebsablauf des Codes ohne die Notwendigkeit, auf den Code selbst abhängig zu werden.

Ein einfaches Beispiel ist, wie immer, Protokollierung. Dass Sie würde eine Dynamic um eine Klasse zu erstellen, dass Sie Fehler haben aus, dass sie die Daten gehen in die Methode protokolliert und fängt alle Ausnahmen und dann protokolliert die Ausnahme.

Mit der intercepter Ihre aktuellen Code hat keine Ahnung, es existiert (vorausgesetzt, Sie Ihre Software in einer entkoppelten Weise mit Schnittstellen richtig aufgebaut haben) und Sie können die Registrierung Ihrer Klassen mit einer Inversion of Control Container ändern Sie die Proxy-Klasse zu verwenden, anstatt ohne eine einzige Zeile sonst wo in Code zu ändern. Dann, wenn Sie den Fehler beheben können Sie die Proxy deaktivieren.

Weitere erweiterte Nutzung von Proxying mit NHibernate zu sehen ist, wo alle der träges Laden durch Proxys behandelt wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top