使用 Castle 创建带有第 3 方 IoC 的 AOP
Using Castle to create AOP with a 3rd party IoC
我正在尝试使用面向方面的编程。问题是有一个内置的自定义 IoC 不支持这种类型的编程。我把问题分解成最重要的部分。我正在使用城堡来实现 AOP。代码注释中描述了这些问题。
我认为我无法做到这一点,因为泛型旨在在编译时已知。但是,我希望社区能比我聪明。
更新 2 - 更新为工作代码(感谢@vasiloreshenski)
using Castle.DynamicProxy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
namespace Tests.Component.CastleTests
{
[TestClass]
public class GenericTest
{
[TestMethod]
public void TestGeneric()
{
IMyPoco mypoco = ContrivedCustomIoc.Create<IMyPoco>();
mypoco.DoWorkNoLogging();
mypoco.DoWork();
//Assert.IsTrue(typeof(MyPoco) == mypoco.GetType());
}
}
public class ContrivedCustomIoc
{
private static Dictionary<string, string> mappings = new Dictionary<string, string>();
static ContrivedCustomIoc()
{
//This comes from XML file
mappings.Add("Tests.Component.CastleTests.IMyPoco", "Tests.Component.CastleTests.MyPoco");
}
public static T Create<T>() where T : class
{
string contractType = typeof(T).FullName;
Type thisTypeInterface = Type.GetType(contractType);
Type thisTypeConcrete = Type.GetType(mappings[contractType]);
//Things work up until this point just fine
//return (T)Activator.CreateInstance(thisTypeConcrete);
var generator = new Castle.DynamicProxy.ProxyGenerator();
//ERROR. Class to proxy must be a class.
//This is because T is an interface
//Is it possible to use Castle with this custom IoC? I want to avoid replacing the entire IoC
//I'd like to simply get an aspect oriented programming pattern in place
//return generator.CreateClassProxy<T>(new MyLoggingInterceptor());
object result = generator.CreateClassProxy(thisTypeConcrete, ProxyGenerationOptions.Default,
new IInterceptor[1] { new MyLoggingInterceptor() });
return (T) result;
}
}
public interface IMyPoco
{
void DoWorkNoLogging();
void DoWork();
}
public class MyPoco : IMyPoco
{
public void DoWorkNoLogging()
{
Console.Write(("Work bein done without logging"));
}
public virtual void DoWork()
{
Console.WriteLine("Work bein done!");
}
}
public class MyLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
Console.WriteLine("Interceptor starting");
invocation.Proceed();
Console.WriteLine("Interceptor ending");
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
Console.WriteLine("Exiting from interceptor");
}
}
}
}
注意:这是导致成功调用拦截器的注释摘要。
- 使用接受运行时类型的 caste proxy generator 的重载。
- 为了执行拦截器,您需要在要拦截的 class 实现中使用虚方法。
我正在尝试使用面向方面的编程。问题是有一个内置的自定义 IoC 不支持这种类型的编程。我把问题分解成最重要的部分。我正在使用城堡来实现 AOP。代码注释中描述了这些问题。
我认为我无法做到这一点,因为泛型旨在在编译时已知。但是,我希望社区能比我聪明。
更新 2 - 更新为工作代码(感谢@vasiloreshenski)
using Castle.DynamicProxy;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
namespace Tests.Component.CastleTests
{
[TestClass]
public class GenericTest
{
[TestMethod]
public void TestGeneric()
{
IMyPoco mypoco = ContrivedCustomIoc.Create<IMyPoco>();
mypoco.DoWorkNoLogging();
mypoco.DoWork();
//Assert.IsTrue(typeof(MyPoco) == mypoco.GetType());
}
}
public class ContrivedCustomIoc
{
private static Dictionary<string, string> mappings = new Dictionary<string, string>();
static ContrivedCustomIoc()
{
//This comes from XML file
mappings.Add("Tests.Component.CastleTests.IMyPoco", "Tests.Component.CastleTests.MyPoco");
}
public static T Create<T>() where T : class
{
string contractType = typeof(T).FullName;
Type thisTypeInterface = Type.GetType(contractType);
Type thisTypeConcrete = Type.GetType(mappings[contractType]);
//Things work up until this point just fine
//return (T)Activator.CreateInstance(thisTypeConcrete);
var generator = new Castle.DynamicProxy.ProxyGenerator();
//ERROR. Class to proxy must be a class.
//This is because T is an interface
//Is it possible to use Castle with this custom IoC? I want to avoid replacing the entire IoC
//I'd like to simply get an aspect oriented programming pattern in place
//return generator.CreateClassProxy<T>(new MyLoggingInterceptor());
object result = generator.CreateClassProxy(thisTypeConcrete, ProxyGenerationOptions.Default,
new IInterceptor[1] { new MyLoggingInterceptor() });
return (T) result;
}
}
public interface IMyPoco
{
void DoWorkNoLogging();
void DoWork();
}
public class MyPoco : IMyPoco
{
public void DoWorkNoLogging()
{
Console.Write(("Work bein done without logging"));
}
public virtual void DoWork()
{
Console.WriteLine("Work bein done!");
}
}
public class MyLoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
Console.WriteLine("Interceptor starting");
invocation.Proceed();
Console.WriteLine("Interceptor ending");
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
finally
{
Console.WriteLine("Exiting from interceptor");
}
}
}
}
注意:这是导致成功调用拦截器的注释摘要。
- 使用接受运行时类型的 caste proxy generator 的重载。
- 为了执行拦截器,您需要在要拦截的 class 实现中使用虚方法。