0

Je veux « injecter » les aspects AOP sur une classe de domaine POCO en utilisant un conteneur de l'unité au moment où l'objet POCO est construit à partir de la base de données par Entity Framework ORMUnité AOP et EF POCO meilleur flux de travail

unité peut facilement « injecter » les aspects AOP sur une classe POCO à l'aide de deux façons (nous allons analyser les avantages et les inconvénients)

1) Interface Interceptor

vous obtenez un proxy objet non objet Derived de votre classe POCO.

VOUS POUVEZ AJOUTER APO À UN OBJET POCO PRÉCÉDEMMENT EXISTANT, VOUS N'AVEZ PAS BESOIN D'EN INSTAURER UN NOUVEAU.

ou

2) VirtualMethod Interceptor

vous obtenez un objet qui est un objet Derived de votre classe POCO.

Vous NE POUVEZ PAS AJOUTER AOP A UN OBJET POCO EXISTANT PRECEDEMMENT, VOUS DEVEZ EN INSTAURER UN NOUVEAU.

En outre .. nous pouvons. A12) CONFIGUREZ LE RÉCIPIENT Unity et utilisez la méthode Resolve.

ou

b) manualy DO L'injection AOP par la classe Intercept sans avoir à configurer un CONTAINER unité.

Je pouvais également récupérer les objets POCO de la base de données via EF, puis utiliser la classe Intercept avec un Intercepteur d'interface juste pour injecter AOP sur les objets précédemment récupérés. Mais le résultat ne sera pas dérivé de l'objet de la classe POCO. Donc, ce dont j'aurais besoin sur un point EF (événement) est de dire à EF qu'il doit utiliser le conteneur Unity pour résoudre la classe POCO (ou utiliser la classe Intercept avec un intercepteur VirtualMethod), donc l'AOP sera injecté et l'objet sera dérivé de la classe POCO.

BR Alex

Répondre

0

J'envisage d'utiliser PostSharp pour de telles interceptions

Mais si j'ai été forcé d'utiliser l'unité pour le faire, la seule approche que je puisse imaginer est d'utiliser une interface pour la résolution et Motif de décorateur. L'inconvénient est que la mise en œuvre sera fastidieuse et moins facile à maintenir à long terme.

intéressant de mentionner que vous DEVRIEZ propriétés jamais accès non déclarés sur l'interface NI pointée par le décorateur, car les modifications à ces propriétés ne seront pas reflétées

Cependant, comme un exercice ci-dessous le code qui pourrait être mis en œuvre

public interface IProduct 
{ 
    int ProductID { get; set; } 
    string ProductName { get; set; } 
    decimal? UnitPrice { get; set; } 
} 

public class Product : IProduct 
{ 
    public virtual int ProductID { get; set; } 
    public virtual string ProductName { get; set; } 
    public int? SupplierID { get; set; } 
    public int? CategoryID { get; set; } 
    public string QuantityPerUnit { get; set; } 
    public virtual decimal? UnitPrice { get; set; } 
    public short? UnitsInStock { get; set; } 
    public short? UnitsOnOrder { get; set; } 
    public short? ReorderLevel { get; set; } 
    public bool Discontinued { get; set; } 
} 

public class AopProduct : Product 
{ 
    private readonly IProduct _product; 

    public override int ProductID { get { return _product.ProductID; } set { _product.ProductID = value; } } 
    public override string ProductName { get { return _product.ProductName; } set { _product.ProductName = value; } } 
    public override decimal? UnitPrice { get { return _product.UnitPrice; } set { _product.UnitPrice = value; } } 

    public AopProduct(IProduct product) 
    { 
     _product = Intercept.ThroughProxy(product, new InterfaceInterceptor(), new IInterceptionBehavior[] { new LoggingInterceptionBehavior() }); 
    } 
} 

public class LoggingInterceptionBehavior : IInterceptionBehavior 
{ 
    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 
    { 
     Console.WriteLine("Invoking {0} at {1}", input.MethodBase.Name, DateTime.Now.ToLongTimeString()); 
     return getNext()(input, getNext); 
    } 

    public IEnumerable<Type> GetRequiredInterfaces() 
    { 
     return Type.EmptyTypes; 
    } 

    public bool WillExecute => true; 
} 

[TestClass] 
public class UnitTest 
{ 
    [TestMethod] 
    public void AopProductShouldHaveAspectsAndBeProduct() 
    { 
     var product = new Product(); 

     var aopProduct = new AopProduct(product) { ProductID = 100, ProductName = "a product", UnitPrice = 12.5m }; 

     DisplayProduct(aopProduct); 

     Assert.IsTrue(aopProduct is Product); 
    } 

    private static void DisplayProduct(Product product) 
    { 
     Console.WriteLine($"{product.ProductID} - {product.ProductName} - {product.UnitPrice}"); 
    } 
} 

Si nous courons le code montre

Invoquer set_ProductID à 0:53:36

invocation set_ProductID à 0:53:36

invocation set_ProductName à 0:53:36

invocation set_ProductName à 0:53:36

invocation set_UnitPrice à 0:53:36

Invoking set_UnitPrice à 0:53:36

Invoking get_ProductID à 0:53:36

Invoking get_ProductID à 00:53:36

invocation get_ProductName à 0:53:36

Invoking get_ProductName à 0:53:36

Invoking get_UnitPrice à 0:53:36

Invoking get_UnitPrice à 00:53:36

100 - un produit - 12,5

0

Maintenant, comparez la solution PostSharp, vous n'avez besoin de rien de plus, pas d'interface, pas de décorateur, pas d'unité, juste votre classe POCO ordinaire. Je n'avais "marqué" que des propriétés virtuelles juste pour les distinguer de celles que je ne veux pas attacher d'aspects, mais c'est à vous de décider comment appliquer les aspects.

public class Product 
{ 
    public virtual int ProductID { get; set; } 
    public virtual string ProductName { get; set; } 
    public int? SupplierID { get; set; } 
    public int? CategoryID { get; set; } 
    public string QuantityPerUnit { get; set; } 
    public virtual decimal? UnitPrice { get; set; } 
    public short? UnitsInStock { get; set; } 
    public short? UnitsOnOrder { get; set; } 
    public short? ReorderLevel { get; set; } 
    public bool Discontinued { get; set; } 
} 

[Serializable] 
public sealed class LoggingOnMethodBoundaryAspect : OnMethodBoundaryAspect 
{ 
    public override void OnEntry(MethodExecutionArgs args) 
    { 
     Console.WriteLine("Invoking {0} at {1}", args.Method.Name, DateTime.Now.ToLongTimeString()); 
    } 
} 

[TestClass] 
public class UnitTest 
{ 


    [TestMethod] 
    public void PSharpAopProductShouldHaveAspectsAndBeProduct() 
    { 
     var product = new Product() { ProductID = 100, ProductName = "a product", UnitPrice = 12.5m }; 

     DisplayProduct(product); 
    } 

    private static void DisplayProduct(Product product) 
    { 
     Console.WriteLine($"{product.ProductID} - {product.ProductName} - {product.UnitPrice}"); 
    } 

} 

et les GlobalAspects.Contenu du fichier cs

using PostSharp.Extensibility; 

[assembly: LoggingOnMethodBoundaryAspect(AttributeTargetTypes = "EFUnityAOPTest.Product", AttributeTargetTypeAttributes = MulticastAttributes.Public, AttributeTargetMemberAttributes = MulticastAttributes.Virtual)] 

Si nous courons le code montre

Invoquer set_ProductID à 1:10:39

Invoquer set_ProductName à 1:10:39

Invoquer set_UnitPrice à 01h10 : 39

Invoquer get_ProductID à 1:10:39

I nvoking get_ProductName à 01:10:39

Invoking get_UnitPrice à 01:10:39

100 - un produit - 12,5

Bonne codage

BR Alex