凯旋门074网址,《asp.net-mvc框架揭秘》一书中,有个示范,是应用unity容器来注入自定义的调整器工厂。代码示例能够团结去下载源码,在这里笔者就不说了。IOC容器的面目是解耦的实例化接口类,而什么完毕解耦就是经过第三方容器来实例化,在此地是unity容器,而不是在品种中实例化接口类。实例化的不二等秘书技只有正是反光,Emit,表明式树,委托等四个艺术。Unity容器的IOC使用首要是多少个个情势:Register,Resolver,Dispose。后边一个注册接口和接口类,前者将接口类的实例化转移到第三方容器中完成。而那边的Dispose却是有一点文章了。假诺单单是控制台的施用类型,就没有需要多说,假若是在mvc框架中的话,大家的接口类的财富自由应该投身什么地点正好呢?微软unity开辟小组给我们做了很好的分解,原来的书文:
咱俩将Unity容器里面财富的刑满释放解除劳教与调节器的财富自由绑定在联合。怎样用代码来代表?大家在基于Unity的调控器工厂中的GetControllerInstance中深入分析controllerType对象,而不是分析某些接口:
(IController)this.UnityContainer.Resolve(controllerType);
就算Unity容器是IOC框架,我们仍是能够动用unity来做AOP,能够参见的合法材料:澳门凯旋门注册网址,(5 – Interception
using
Unity).aspx)

咱们第一是通过集成ICallHandler接口来促成AOP,这么些接口是unity给我们提供的,那么些接口首要正是一个Invoke方法。承继自ICallHandler接口的类(TCalHandler),当通过接口(TIOCInterface)早先调用类(TIOCImple)中的方法时,就能够先导调用类(TCalHandler)的Invoke方法。
在Invoke中,要是调用getNext()方法就能够调用IOCImple标明了品质的法门。若是你的C#澳门凯旋门注册网址而不是在项目中实例化接口类。基础相比扎实,你对C#澳门凯旋门注册网址而不是在项目中实例化接口类。中的一个最重要知识点-天性(attribute)应该就能够有印象以及自然的问询。asp.net-mvc框架中的过滤器就是依据attribute达成的。那么在此地也是,大家须求调用unity给我们提供的叁个表征attribute-HandlerAttribute,在此处大家调用大家依照ICallHandler的类。
DI是为着解耦的实例化接口,而AOP是横向的注入一些逻辑,大家能够在AOP里面完毕DI,unity中的AOP模块暗中认可会给大家落到实处DI,一旦我们落到实处了AOP,就也正是完毕了DI。作者会挑一些代码片段来分解。代码来自<<asp.net-mvc框架揭秘>>的第14章S1401源码。首先我们落实自身自定义的调整器工厂:

澳门凯旋门注册网址 1澳门凯旋门注册网址 2

public class UnityControllerFactory : DefaultControllerFactory
{
    public IUnityContainer UnityContainer { get; private set; }

    public UnityControllerFactory(IUnityContainer unityContainer)
    {
        this.UnityContainer = unityContainer;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (null == controllerType)
        {
            return null;
        }
        return (IController)this.UnityContainer.Resolve(controllerType);
    }
}

View Code

前面说过的unity的DI对象 Resolve是在此间达成的。

澳门凯旋门注册网址而不是在项目中实例化接口类。小编们定义了一个接口ITimeProvider和接口达成类DefaultTimeProvider,然后我们依据ICallHandler接口落成二个类:

澳门凯旋门注册网址 3澳门凯旋门注册网址 4

public class CachingCallHandler : ICallHandler
{
    public int Order { get ; set ; }

    public TimeSpan ExpirationTime { get; private set; }

    public static TimeSpan DefaultExpirationTime { get; private set; }

    public static Func<MethodBase, object[], string> CacheKeyGenerator { get; private set; }

    // 静态构造函数,只调用一次,并且是最先调用的
    static CachingCallHandler()
    {
        DefaultExpirationTime = new TimeSpan(0, 5, 0);
        Guid prefix = Guid.NewGuid();

        CacheKeyGenerator = (method, inputs) =>
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendFormat("{0}: ", prefix);
            sb.AppendFormat("{0}: ", method.DeclaringType);
            sb.AppendFormat("{0}: ", method.Name);

            if (inputs != null)
            {
                foreach (var input in inputs)
                {
                    string hashCode = (input == null) ? "" : input.GetHashCode().ToString();
                    sb.AppendFormat("{0}: ", hashCode);
                }
            }
            return sb.ToString().TrimEnd(':');
        };

    }

    public CachingCallHandler(TimeSpan? expirationTime=null)
    {
        this.ExpirationTime = expirationTime.HasValue ? expirationTime.Value : DefaultExpirationTime;
    }

    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        MethodInfo targetMethod = (MethodInfo)input.MethodBase;

        if(targetMethod.ReturnType == typeof(void))
        {
            return getNext()(input, getNext);
        }

        object[] inputs = new object[input.Inputs.Count];
        input.Inputs.CopyTo(inputs, 0);
        string cacheKey = CacheKeyGenerator(targetMethod, inputs);

        object[] cachedResult = HttpRuntime.Cache.Get(cacheKey) as object[];

        if (null == cachedResult)
        {
            IMethodReturn realReturn = getNext()(input, getNext);
            if(null == realReturn.Exception)
            {
                HttpRuntime.Cache.Insert(cacheKey, new object[] { realReturn.ReturnValue }, null, DateTime.Now.Add(this.ExpirationTime), Cache.NoSlidingExpiration);
            }
            return realReturn;
        }
        return input.CreateMethodReturn(cachedResult[0], new object[] { input.Arguments });

    }
}

View Code

澳门凯旋门注册网址而不是在项目中实例化接口类。Invoke方法的调用是在ITimeProvider对象调用其内的接口时候接触调用的。
接下去基于HandlerAttribute来落实二个类:

澳门凯旋门注册网址 5澳门凯旋门注册网址 6

public class CachingCallHandlerAttribute : HandlerAttribute
{
    public TimeSpan? ExpirationTime { get; private set; }

    public CachingCallHandlerAttribute(string expirationTime ="")
    {
        if(!string.IsNullOrEmpty(expirationTime))
        {
            TimeSpan expirationTimeSpan;
            if(!TimeSpan.TryParse(expirationTime, out expirationTimeSpan))
            {
                throw new ArgumentException("输入过期时间(TimeSpan) 不合法");
            }
            this.ExpirationTime = expirationTimeSpan;
        }
    }

    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new CachingCallHandler(this.ExpirationTime) { Order = this.Order };
    }
}

View Code

接下去大家Global.asax中,达成AOP的注入:

澳门凯旋门注册网址 7澳门凯旋门注册网址 8

IUnityContainer UnityContainer= new UnityContainer()
.AddNewExtension<Interception>()
.RegisterType<ITimeProvider, DefaultTimeProvider>();

UnityContainer.Configure<Interception>()
.SetInterceptorFor<ITimeProvider>(new InterfaceInterceptor());

UnityControllerFactory controllerFactory = new UnityControllerFactory(UnityContainer);

ControllerBuilder.Current.SetControllerFactory(controllerFactory);

View Code

末尾便是运用了:

澳门凯旋门注册网址 9澳门凯旋门注册网址 10

public class HomeController : Controller
{
    public ITimeProvider TimeProvider;
    public HomeController(ITimeProvider _time)
    {
        TimeProvider = _time;
    }

    public void Index()
    {
        for (int i = 0; i < 3; i++)
        {
            Response.Write(string.Format("{0}: {1: hh:mm:ss}<br/>", "Utc", this.TimeProvider.GetCurrentTime(DateTimeKind.Utc)));
            Thread.Sleep(1000);

            Response.Write(string.Format("{0}: {1: hh:mm:ss}<br/><br/>", "Local", this.TimeProvider.GetCurrentTime(DateTimeKind.Local)));
            Thread.Sleep(1000);
        }
    }
}

View Code

在此地TimeProvider调用期内的方式GetCurrentTime方法时就能调用Invoke方法。Invoke方法的参数GetNextHandlerDelegate类的变量在Invoke中的调用代表着真正的调用GetCurrentTime方法。其实大家能够这么实现:

澳门凯旋门注册网址 11澳门凯旋门注册网址 12

public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{

    var retvalue = getNext()(input, getNext);
    if(retvalue.Exception!=null)
    {
        Console.WriteLine("error");
    }
    return retvalue;
}

View Code

这种简易的兑现是一心能够的。

建议看看微软官方的材质
代码地址:链接:
密码:b9pj

相关文章