Unity容器使用笔记

1、配置文件Unity容器使用笔记
说明:此处有两个容器的节点,用来分别初始化两个容器,可以应对需要注入两个dbContext的情况。
代码:
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
</configSections>
<unity>
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
<containers>
<container name="yydyoaSection">
<extension type="Interception"/>
<register type="Study.Unity.Interface.IDoWork,Study.Unity" mapTo=" Study.Unity.Service.StudentDoWork,Study.Unity">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="Study.Unity.Aop.ParameterCheckBehavior,Study.Unity"/>
<interceptionBehavior type="Study.Unity.Aop.CachingBehavior,Study.Unity"/>
<interceptionBehavior type="Study.Unity.Aop.ExpessionBehavior,Study.Unity"/>
<interceptionBehavior type="Study.Unity.Aop.LogBeforeBehavior,Study.Unity"/>
</register>
</container>
<container name="managerSection">
<extension type="Interception"/>
<register type="Study.Unity.Interface.IDoWork,Study.Unity" mapTo=" Study.Unity.Service.TeacherDoWork,Study.Unity">
<interceptor type="InterfaceInterceptor"/>
</register>
</container>
</containers>
</unity>
</configuration>

2、初始化容器
说明:创建了一个枚举,用来对应配置文件中的两个节点,然后通过扩展方法获取到枚举值在配置文件中的节点名称,用来分别初始化不同的容器。
代码:
容器的工厂:
public class DIFactory
{
private static readonly object _SyncHelper = new object();
private static volatile Dictionary<EnContainer, IUnityContainer> _UnityContainerDictionary = new Dictionary<EnContainer, IUnityContainer>();

    public static IUnityContainer GetContainer(EnContainer enContainer)
    {
        if (!_UnityContainerDictionary.ContainsKey(enContainer))
        {
            lock (_SyncHelper)
            {
                if (!_UnityContainerDictionary.ContainsKey(enContainer))
                {
                    //配置UnityContainer
                    IUnityContainer container = new UnityContainer();
                    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                    fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");
                    Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                    UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);
                    string strSection = enContainer.Speccn();
                    configSection.Configure(container, strSection);

                    _UnityContainerDictionary.Add(enContainer, container);
                }
            }
        }
        return _UnityContainerDictionary[enContainer];
    }
}
    枚举:
     public enum EnContainer
{
    [Speccn("yydyoaSection")]
    YYDYOA = 1,
    [Speccn("managerSection")]
    MANAGER = 2
}
    特性:
     [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SpeccnAttribute : Attribute
{
    private string Speccn { get; set; }
    public SpeccnAttribute(string speccn)
    {
        this.Speccn = speccn;
    }
    public string GetSpeccn()
    {
        return this.Speccn;
    }
}
    扩展方法:   
 public static class EnumExtend
{
    public static string Speccn(this Enum enContainer)
    {
        Type type = enContainer.GetType();
        FieldInfo field = type.GetField(enContainer.ToString());
        if (field.IsDefined(typeof(SpeccnAttribute), true))
        {
            SpeccnAttribute speccnAttribute = (SpeccnAttribute)field.GetCustomAttribute(typeof(SpeccnAttribute));
            return speccnAttribute.GetSpeccn();
        }
        else
        {
            return enContainer.ToString();
        }
    }
}

3、接口和实现类的代码
接口:
public interface IDoWork
{
string Show(string arg);
}
实现类:
public class StudentDoWork : IDoWork
{
public string Show(string arg)
{
Console.WriteLine($"{this.GetType().Name}_DoWork Before");
Console.WriteLine($"{this.GetType().Name}_DoWork After");
return nameof(StudentDoWork);
}
}

    public class TeacherDoWork : IDoWork
{
    public string Show(string arg)
    {
        Console.WriteLine($"{this.GetType().Name}_DoWork");
        return nameof(TeacherDoWork);
    }
}

    4、AOP扩展类的代码:
        参数检查:
              public class ParameterCheckBehavior : IInterceptionBehavior
{
    public bool WillExecute => true;

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

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        Console.WriteLine("ParameterCheckBehavior");
        if (input.Inputs[0].ToString().Length < 10)//可以过滤一下敏感词
        {
            //返回一个异常
            return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));
        }
        else
        {
            Console.WriteLine("参数检测无误");
            return getNext().Invoke(input, getNext);
        }
    }
}

    日志:
     public class LogBeforeBehavior : IInterceptionBehavior
{
    public bool WillExecute => true;

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

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        Console.WriteLine("LogBehavior before");
        IMethodReturn method = getNext()(input, getNext);
        Console.WriteLine("LogBehavior after");
        return method;
    }
}

    异常:
     public class ExpessionBehavior : IInterceptionBehavior
{
    public bool WillExecute => true;

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

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        Console.WriteLine("ExpessionBehavior before");

        IMethodReturn method = getNext()(input, getNext);
        if (method.Exception != null)
            Console.WriteLine($"异常:{method.Exception.Message}");
        Console.WriteLine("ExpessionBehavior after");
        return method;
    }
}

    缓存:
      public class CachingBehavior : IInterceptionBehavior
{
    public IEnumerable<Type> GetRequiredInterfaces()
    {
        return Type.EmptyTypes;
    }

    private static Dictionary<string, object> CachingBehaviorDictionary = new Dictionary<string, object>();

    public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
    {
        string key = $"{input.MethodBase.Name}_{Newtonsoft.Json.JsonConvert.SerializeObject(input.Inputs)}";
        if (CachingBehaviorDictionary.ContainsKey(key))
        {
            return input.CreateMethodReturn(CachingBehaviorDictionary[key]);
        }
        else
        {
            IMethodReturn result = getNext().Invoke(input, getNext);
            if (result.ReturnValue != null)
            {
                CachingBehaviorDictionary.Add(key, result.ReturnValue);
                Console.WriteLine("CachingBehavior");
            }
            return result;
        }
    }

    public bool WillExecute
    {
        get { return true; }
    }
}

    5、测试代码
         static void Main(string[] args)
    {
        IUnityContainer yydyoaContainer = DIFactory.GetContainer(EnContainer.YYDYOA);
        IDoWork doWork = yydyoaContainer.Resolve<IDoWork>();
        doWork.Show("12345678901234");
        yydyoaContainer = DIFactory.GetContainer(EnContainer.MANAGER);
        doWork = yydyoaContainer.Resolve<IDoWork>();
        doWork.Show("123");
        Console.ReadKey();
    }
    6、总结
        AOP扩展的进入顺序是根据配置文件从上到下进入,业务逻辑与拓展逻辑的执行顺序是根据getNext().Invoke(input, getNext)代码的位置决定。

猜你喜欢

转载自blog.51cto.com/3544640/2139792