.NET程序中,可以利用Unity来实现AOP,用来进行日志、缓存或权限的处理。这里我们来写一个简单的程序,让其实现简单的AOP功能。
1.使用NuGet,在项目中获取Microsoft.Practices.Unity。
2.新建一个ITalk类及其实现
public interface ITalk { string Speak(string msg); } public class Talk : ITalk { public string Speak(string msg) { Console.WriteLine(msg); return msg; } }
3.再进一个ServiceLocator类,用来实现接口的依赖反转
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.Configuration; using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Reflection; namespace AopDemo { /// <summary> /// Represents the Service Locator. /// </summary> public sealed class ServiceLocator : IServiceProvider { #region Private Fields private readonly IUnityContainer container; #endregion #region Private Static Fields private static readonly ServiceLocator instance = new ServiceLocator(); #endregion #region Ctor /// <summary> /// Initializes a new instance of <c>ServiceLocator</c> class. /// </summary> private ServiceLocator() { UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity"); container = new UnityContainer(); section.Configure(container); } #endregion #region Public Static Properties /// <summary> /// Gets the singleton instance of the <c>ServiceLocator</c> class. /// </summary> public static ServiceLocator Instance { get { return instance; } } #endregion #region Private Methods private IEnumerable<ParameterOverride> GetParameterOverrides(object overridedArguments) { List<ParameterOverride> overrides = new List<ParameterOverride>(); Type argumentsType = overridedArguments.GetType(); argumentsType.GetProperties(BindingFlags.Public | BindingFlags.Instance) .ToList() .ForEach(property => { var propertyValue = property.GetValue(overridedArguments, null); var propertyName = property.Name; overrides.Add(new ParameterOverride(propertyName, propertyValue)); }); return overrides; } #endregion #region Public Methods /// <summary> /// Gets the service instance with the given type. /// </summary> /// <typeparam name="T">The type of the service.</typeparam> /// <returns>The service instance.</returns> public T GetService<T>() { return container.Resolve<T>(); } /// <summary> /// Gets the service instance with the given type by using the overrided arguments. /// </summary> /// <typeparam name="T">The type of the service.</typeparam> /// <param name="overridedArguments">The overrided arguments.</param> /// <returns>The service instance.</returns> public T GetService<T>(object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve<T>(overrides.ToArray()); } /// <summary> /// Gets the service instance with the given type by using the overrided arguments. /// </summary> /// <param name="serviceType">The type of the service.</param> /// <param name="overridedArguments">The overrided arguments.</param> /// <returns>The service instance.</returns> public object GetService(Type serviceType, object overridedArguments) { var overrides = GetParameterOverrides(overridedArguments); return container.Resolve(serviceType, overrides.ToArray()); } #endregion #region IServiceProvider Members /// <summary> /// Gets the service instance with the given type. /// </summary> /// <param name="serviceType">The type of the service.</param> /// <returns>The service instance.</returns> public object GetService(Type serviceType) { return container.Resolve(serviceType); } #endregion } }
4.接下来是错误和缓存处理的类。我们这边只是简单的在控制台输出一句话,证明代码有执行。
ExceptionLoggingBehavior.cs
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class ExceptionLoggingBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("ExceptionLoggingBehavior"); return getNext().Invoke(input, getNext); } public bool WillExecute { get { return true; } } }
CachingBehavior.cs
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public class CachingBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("CachingBehavior"); return getNext().Invoke(input, getNext); } public bool WillExecute { get { return true; } } }
5.配置App.Config文件
<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> </configSections> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> <!--BEGIN: Unity--> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/> <container> <extension type="Interception"/> <!--Cache Provider--> <register type="AopDemo.ITalk, AopDemo" mapTo="AopDemo.Talk, AopDemo"> <interceptor type="InterfaceInterceptor"/> <interceptionBehavior type="AopDemo.InterceptionBehaviors.CachingBehavior, AopDemo"/> <interceptionBehavior type="AopDemo.InterceptionBehaviors.ExceptionLoggingBehavior, AopDemo"/> </register> </container> </unity> <!--END: Unity--> </configuration>
6.调用
static void Main(string[] args) { ITalk talk = ServiceLocator.Instance.GetService<ITalk>(); talk.Speak("Hello"); }
7.结果
可以看到在打印出Hello前,代码先执行到了缓存与错误处理的方法。
PS:如果IOC的时候报类似错误
Exception is: InvalidOperationException - The type OAManageClient has multiple constructors of length 2. Unable to disambiguate.则配置文件应该增加<constructor></constructor>
<register type="AopDemo.ITalk, AopDemo" mapTo="AopDemo.Talk, AopDemo"> <interceptor type="InterfaceInterceptor"/> <interceptionBehavior type="AopDemo.InterceptionBehaviors.CachingBehavior, AopDemo"/> <interceptionBehavior type="AopDemo.InterceptionBehaviors.ExceptionLoggingBehavior, AopDemo"/> <constructor></constructor> </register>