我希望在Entity Framework ORM从数据库构建POCO对象时,使用Unity容器在域POCO类上“注入”AOP方面
Unity可以使用两种方式轻松地在POCO类中“注入”AOP方面(让我们分析优缺点)
1)接口拦截器
您获得的代理OBJECT不是POCO类的DERIVED对象。
您可以将APO添加到以前存在的POCO对象中,您不需要安装新的POCO对象。
或
2)VirtualMethod拦截器
你得到一个对象,它是你的POCO类的一个派生对象。
你不能添加AOP到一个以前存在的POCO对象,你需要安装一个新的。
此外..我们可以。
a)配置Unity CONTAINER并使用Resolve方法。
或
b)MANUALY通过Intercept类进行AOP注入而无需配置Unity CONTAINER。
我还可以通过EF从数据库中检索POCO对象,然后使用带有接口拦截器的Intercept类,只是为了在先前检索的对象上注入AOP。但结果不会是POCO类的派生对象。
所以我需要在一些EF点(事件)上告诉EF它必须使用Unity容器来解析POCO类(或者使用带有VirtualMethod拦截器的Intercept类),因此将注入AOP该对象将派生于POCO类。
BR Alex
答案 0 :(得分:0)
我正在考虑使用PostSharp进行此类拦截
但如果我被迫使用Unity来做,我能想象的唯一方法就是使用一个接口来解析和一个装饰模式。
缺点是实施起来很乏味,长期来说不易维护。
值得一提的是,您不应该访问未在装饰器指向的NOR接口上声明的属性,因为不会反映对这些属性的更改
但是,在下面的练习中可以实现的代码
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}");
}
}
如果我们运行代码显示
在0:53:36调用set_ProductID
在0:53:36调用set_ProductID
在0:53:36调用set_ProductName
在0:53:36调用set_ProductName
在0:53:36调用set_UnitPrice
在0:53:36调用set_UnitPrice
在0:53:36调用get_ProductID
在0:53:36调用get_ProductID
在0:53:36调用get_ProductName
在0:53:36调用get_ProductName
在0:53:36调用get_UnitPrice
在0:53:36调用get_UnitPrice
100 - 产品--12,5
答案 1 :(得分:0)
现在比较PostSharp解决方案,你不需要额外的,没有接口,没有装饰器,没有Unity,只需你的普通POCO类。 我只是将某些属性“标记”为虚拟属性,以区别于我不想附加方面的属性,但由您来决定如何应用这些方面。
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}");
}
}
和GlobalAspects.cs文件内容
using PostSharp.Extensibility;
[assembly: LoggingOnMethodBoundaryAspect(AttributeTargetTypes = "EFUnityAOPTest.Product", AttributeTargetTypeAttributes = MulticastAttributes.Public, AttributeTargetMemberAttributes = MulticastAttributes.Virtual)]
如果我们运行代码显示
在1:10:39调用set_ProductID
在1:10:39调用set_ProductName
在1:10:39调用set_UnitPrice
在1:10:39调用get_ProductID
在1:10:39调用get_ProductName
在1:10:39调用get_UnitPrice
100 - 产品--12,5
快乐编码
BR Alex