主頁 > .NET開發 > IOC控制反轉、Unity簡介

IOC控制反轉、Unity簡介

2020-09-12 08:00:22 .NET開發

參考博客地址:

 

Unity系列文章,推薦:http://www.cnblogs.com/qqlin/archive/2012/10/16/2717964.html

https://www.cnblogs.com/lyps/p/10560256.html

 

這篇文章主要介紹.NET Framework下面的IOC以及Unity的使用,下一篇文章介紹.NET Core下面自帶的容器IServiceCollection以及Autofac的使用https://www.cnblogs.com/taotaozhuanyong/p/11562184.html

IOC(Inverse of Control),控制反轉,

說到IOC,就不得不提DI(Dependency Injection),依賴注入

IOC是目標效果,需要DI依賴注入的手段,

分層架構時這些是必須的,可以劃分邊界獨立演化,也方便分工,促進代碼復用,,

依賴倒置原則DIP:

  系統架構時,高層模塊不應該依賴于低層模塊,二者通過抽象來依賴,依賴抽象而不是依賴細節,在A勒種呼叫了B類,A類就是高層,B類就是低層,

面向抽象:

  1、一個方法滿足多種型別

  2、支持下層的擴展,

下面有三種創建一個物件的方式:

AndroidPhone phone = new AndroidPhone();//1 全是細節

IPhone phone = new AndroidPhone();//2 左邊抽象右邊細節

IPhone phone = ObjectFactory.CreatePhone();//3 封裝轉移
/// <summary>
/// 簡單工廠+組態檔+反射
/// </summary>
public class ObjectFactory
{
    public static IPhone CreatePhone()
    {
        string classModule = ConfigurationManager.AppSettings["iPhoneType"];
        Assembly assemly = Assembly.Load(classModule.Split(',')[1]);
        Type type = assemly.GetType(classModule.Split(',')[0]);
        return (IPhone)Activator.CreateInstance(type);//無引數建構式
    }

    public static IPhone CreatePhone(IBaseBll iBLL)
    {
        string classModule = ConfigurationManager.AppSettings["iPhoneType"];
        Assembly assemly = Assembly.Load(classModule.Split(',')[1]);
        Type type = assemly.GetType(classModule.Split(',')[0]);
        return (IPhone)Activator.CreateInstance(type, new object[] { iBLL });
    }
}

在App.config下面配置節點:

<appSettings>
    <add key="iPhoneType" value="Bingle.Service.AndroidPhone,Bingle.Service" />
  </appSettings>

只有抽象,沒有細節,好處是可擴展,

IOC控制反轉:

  傳統開發,上端依賴(呼叫/指定)下端物件,這個樣子會有依賴,控制反轉就是把對下端物件的依賴轉移到第三方容器(工廠+組態檔+反射),能夠讓程式擁有更好的擴展性,

下面出現一個問題:

  構造A物件,但是A依賴于B物件,那就先構造B,如果B又依賴C,再構造C,,,,,,

IDAL.IBaseDAL baseDAL = new DAL.BaseDAL();
IBLL.IBaseBll baseBll = new BLL.BaseBll(baseDAL);
IPhone phone = ObjectFactory.CreatePhone(baseBll);

現在這個問題已經暴露了,下面開始了DI,依賴注入,就能做到構造某個物件時,將依賴的物件自動初始化并注入,

IOC是目標效果,需要DI依賴注入的手段,

DI依賴注入:

  三種方式注入:建構式注入、屬性注入、方法注入(按照時間順序)

  [Dependency]//屬性注入

 [Dependency]//屬性注入
 public IMicrophone iMicrophone { get; set; }

  [InjectionConstructor]//建構式注入,默認找引數最多的建構式,方法注入不加這個特性也是可以的,可以不用特性,可以去掉對容器的依賴

[InjectionConstructor]//建構式注入:默認找引數最多的建構式
public ApplePhoneUpdate(IHeadphone headphone)
{
    this.iHeadphone = headphone;
    Console.WriteLine("{0} 帶引數建構式", this.GetType().Name);
}

  [InjectionMethod]//方法注入

 [InjectionMethod]//方法注入
 public void Init(IPower power)
 {
     this.iPower = power;
 }

如何使用Unity容器?

  1、安裝Unity

  

 

   2、容器三部曲:

    實體化容器、注冊型別、獲取實體

  3、專案版本和服務處的版本要一直,

下面是Iphone與AndroidPhone的定義:

 public interface IPhone
 {
     void Call();
     IMicrophone iMicrophone { get; set; }
     IHeadphone iHeadphone { get; set; }
     IPower iPower { get; set; }
 }




 public class AndroidPhone : IPhone
 {
     public IMicrophone iMicrophone { get; set; }
     public IHeadphone iHeadphone { get; set; }
     public IPower iPower { get; set; }

     //public AndroidPhone()
     //{
     //    Console.WriteLine("{0}建構式", this.GetType().Name);
     //}
     
     public AndroidPhone(AbstractPad pad, IHeadphone headphone)
     {
         Console.WriteLine("{0}建構式", this.GetType().Name);
     }

     //[ElevenInjectionConstructor]
     public AndroidPhone(AbstractPad pad)
     {
         Console.WriteLine("{0}建構式", this.GetType().Name);
     }
     public AndroidPhone(IBaseBll baseBll)
     {
         Console.WriteLine("{0}建構式", this.GetType().Name);
     }

     public void Call()
     {
         Console.WriteLine("{0}打電話", this.GetType().Name); ;
     }
 }
View Code
 IUnityContainer container = new UnityContainer();//1 實體化容器
 container.RegisterType<IPhone, AndroidPhone>();//2 注冊型別
 IPhone iphone = container.Resolve<IPhone>();//3 獲取實體

我們來看一下Unity下面RegisterType方法里面的泛型約束:

 

還有一個方法:

 

 

IUnityContainer container = new UnityContainer();//1 實體化容器

container.RegisterInstance<AbstractPad>(new ApplePadChild());

AbstractPad abstractPad = container.Resolve<AbstractPad>();

后遭的時候,有依賴:

 

 下面來解決這個問題:但是要保持Unity版本一致

下面是一些注冊時要依賴的型別

 public interface IHeadphone
 {

 }

 public class Headphone : IHeadphone
 {
     public Headphone(IMicrophone microphone)
     {
         Console.WriteLine("Headphone 被構造");
     }
 }
public interface IMicrophone
{

}

 public class Microphone : IMicrophone
 {

     public Microphone(IPower power)
     {
         Console.WriteLine("Microphone 被構造");
     }
 }
public interface IPower
{

}

public class Power : IPower
{
    public Power(IBLL.IBaseBll baseBll)
    {
        Console.WriteLine("Power 被構造");
    }
}
 public interface IBaseBll
 {
     void DoSomething();
 }
 public class BaseBll : IBaseBll
 {
     private IBaseDAL _baseDAL = null;
     public BaseBll(IBaseDAL baseDAL, int id)
     {
         Console.WriteLine($"{nameof(BaseBll)}被構造,,,{id},");
         this._baseDAL = baseDAL;
     }
     public void DoSomething()
     {
         this._baseDAL.Add();
         this._baseDAL.Update();
         this._baseDAL.Find();
         this._baseDAL.Delete();
     }
 }

 public interface IBaseDAL
 {
     void Add();
     void Delete();
     void Update();
     void Find();
 }
public class BaseDAL : IBaseDAL
{
    public BaseDAL()
    {
        Console.WriteLine($"{nameof(BaseDAL)}被構造,,,,");
    }

    public void Add()
    {
        Console.WriteLine($"{nameof(Add)}");
    }

    public void Delete()
    {
        Console.WriteLine($"{nameof(Delete)}");
    }

    public void Find()
    {
        Console.WriteLine($"{nameof(Find)}");
    }

    public void Update()
    {
        Console.WriteLine($"{nameof(Update)}");
    }
}
View Code

 

 IUnityContainer container = new UnityContainer();
 container.RegisterType<IPhone, ApplePhone>();
 container.RegisterType<IHeadphone, Headphone>();
 container.RegisterType<IMicrophone, Microphone>();
 container.RegisterType<IPower, Power>();
 container.RegisterType<IBLL.IBaseBll, BLL.BaseBll>();
 container.RegisterType<IDAL.IBaseDAL, Ruamou.DAL.BaseDAL>();
 IPhone iphone = container.Resolve<IPhone>();

但凡是用到了需要的型別,都要給注入進去,不然容器怎么知道型別啊

 

Unity里面到底是怎么實作的?下面,自己來寫一個IOC

1、最最基礎簡陋的版本:

public interface ILTContainer
    {
        void RegisterType<TFrom, TTo>();
        T Resolve<T>();
    }

 /// <summary>
    /// 容器--工廠
    /// </summary>
    public class LTContainer : ILTContainer
    {
        private Dictionary<string, Type> LTDic = new Dictionary<string, Type>();

        public void RegisterType<TFrom, TTo>()
        {
            LTDic.Add(typeof(TFrom).FullName, typeof(TTo));
        }

        public T Resolve<T>()
        {
            Type type = LTDic[typeof(T).FullName];
            return (T)Activator.CreateInstance(type);
        }
    }
}

呼叫一下:

ILTContainer container = new LTContainer();
container.RegisterType<IPerson, Student>();

var person = container.Resolve<IPerson>();

 

2、升級一點點

 

 

  public interface IPerson
    {

    }

    public class Student : IPerson
    {
        [LTInjectionConstructor]
        public Student(Animal animal)
        {
            Console.WriteLine("Student被構造了...");
        }

    }

    public abstract class Animal
    {
    }

    public class Cat : Animal
    {
        public Cat()
        {
            Console.WriteLine("Animal被構造了....");
        }
    }
}
  public interface ILTContainer
    {
        void RegisterType<TFrom, TTo>();
        T Resolve<T>();
    }


    /// <summary>
    /// 容器--工廠
    /// </summary>
    public class LTContainer : ILTContainer
    {
        private Dictionary<string, Type> LTDic = new Dictionary<string, Type>();

        public void RegisterType<TFrom, TTo>()
        {
            LTDic.Add(typeof(TFrom).FullName, typeof(TTo));
        }

        public T Resolve<T>()
        {
            Type type = LTDic[typeof(T).FullName];
            var ctorArray = type.GetConstructors();
            ConstructorInfo ctor = null;
            if (ctorArray.Count(c => c.IsDefined(typeof(LTInjectionConstructorAttribute), true)) > 0)
            {
                ctor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(LTInjectionConstructorAttribute), true));
            }
            else
            {
                ctor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
            }
            List<object> paraList = new List<object>();
            foreach (var item in ctor.GetParameters())
            {
                Type paraType = item.ParameterType;
                Type targetType = this.LTDic[paraType.FullName];
                paraList.Add(Activator.CreateInstance(targetType));
            }
            return (T)Activator.CreateInstance(type, paraList.ToArray());
            //return (T)this.CreateObject(type);

        }

        private object CreateObject(Type type)
        {
            ConstructorInfo[] ctorArray = type.GetConstructors();
            ConstructorInfo ctor = null;
            if (ctorArray.Count(c => c.IsDefined(typeof(LTInjectionConstructorAttribute), true)) > 0)
            {
                ctor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(LTInjectionConstructorAttribute), true));
            }
            else
            {
                ctor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
            }
            List<object> paraList = new List<object>();
            foreach (var parameter in ctor.GetParameters())
            {
                Type paraType = parameter.ParameterType;
                Type targetType = this.LTDic[paraType.FullName];
                object para = this.CreateObject(targetType);
                //遞回:隱形的跳出條件,就是GetParameters結果為空,targetType擁有無引數建構式
                paraList.Add(para);
            }
            return Activator.CreateInstance(type, paraList.ToArray());
        }
        //屬性注入+方法注入?

    }

呼叫一下:

ILTContainer container = new LTContainer();
 ILTContainer container = new LTContainer();
container.RegisterType<IPerson, Student>();
container.RegisterType<Animal, Cat>();
var person = container.Resolve<IPerson>();

3、再升級一點點:

  繼續找出targetType的構造,找出一個合適的建構式,分別構造其引數,繼續...遞回

 

 

 public interface ILTContainer
    {
        void RegisterType<TFrom, TTo>();
        T Resolve<T>();
    }


    /// <summary>
    /// 容器--工廠
    /// </summary>
    public class LTContainer : ILTContainer
    {
        private Dictionary<string, Type> LTDic = new Dictionary<string, Type>();

        public void RegisterType<TFrom, TTo>()
        {
            LTDic.Add(typeof(TFrom).FullName, typeof(TTo));
        }

        public T Resolve<T>()
        {
            Type type = LTDic[typeof(T).FullName];
            //繼續找出targetType的建構式,找出一個合適的建構式,分別構造其引數
            //繼續......遞回
            return (T)this.CreateObject(type);

        }


        public object CreateObject(Type type)
        {
            ConstructorInfo[] ctorArray = type.GetConstructors();
            ConstructorInfo ctor = null;
            if (ctorArray.Count(c => c.IsDefined(typeof(LTContainer), true)) > 0)
            {
                ctor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(LTContainer), true));
            }
            else
            {
                ctor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
            }
            List<object> paraList = new List<object>();
            foreach (var parameter in ctor.GetParameters())
            {
                Type paraType = parameter.ParameterType;
                Type targetType = this.LTDic[paraType.FullName];
                object para = this.CreateObject(targetType);
                //遞回:隱形的跳出條件,就是GetParameters結果為空,targetType擁有無引數建構式
                paraList.Add(para);
            }
            return Activator.CreateInstance(type, paraList.ToArray());
        }
        //屬性注入+方法注入?

    }

 

生命管理周期:

IUnityContainer container = new UnityContainer();

默認瞬時生命周期:每次都是構造一個新的

container.RegisterType<AbstractPad, ApplePad>();
container.RegisterType<AbstractPad, ApplePad>(new TransientLifetimeManager());

全域單例:全域就只有一個該型別實體

非強制性,只有通過容器獲取才是單例;專案中一般推薦容器單例而不是自己寫單例

container.RegisterType<AbstractPad, ApplePad>(new SingletonLifetimeManager());
AbstractPad pad1 = container.Resolve<AbstractPad>();
AbstractPad pad2 = container.Resolve<AbstractPad>();
Console.WriteLine(object.ReferenceEquals(pad1, pad2));

執行緒單例:同一個執行緒就只有一個實體,不同執行緒就是不同實體

container.RegisterType<AbstractPad, ApplePad>(new PerThreadLifetimeManager());
AbstractPad pad1 = null;
AbstractPad pad2 = null;
AbstractPad pad3 = null;

Action act1 = new Action(() =>
                {
                    pad1 = container.Resolve<AbstractPad>();
                    Console.WriteLine($"pad1由執行緒id={Thread.CurrentThread.ManagedThreadId}");
                });
var result1 = act1.BeginInvoke(null, null);

Action act2 = new Action(() =>
{
    pad2 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad2由執行緒id={Thread.CurrentThread.ManagedThreadId}");
});
var result2 = act2.BeginInvoke(t =>
{
    pad3 = container.Resolve<AbstractPad>();
    Console.WriteLine($"pad3由執行緒id={Thread.CurrentThread.ManagedThreadId}");
    Console.WriteLine($"object.ReferenceEquals(pad2, pad3)={object.ReferenceEquals(pad2, pad3)}");
}, null);

act1.EndInvoke(result1);
act2.EndInvoke(result2);

Console.WriteLine($"object.ReferenceEquals(pad1, pad2)={object.ReferenceEquals(pad1, pad2)}");

//ExternallyControlledLifetimeManager 外部可釋放單例
//PerResolveLifetimeManager 回圈參考

 

 自己寫的容器里面,加上生命周期:

 public interface IBingleContainer
 {
     void RegisterType<TFrom, TTo>(LifeTimeType lifeTimeType = LifeTimeType.Transient);
     T Resolve<T>();
 }

 /// <summary>
 /// 容器--工廠
 /// </summary>
 public class BingleContainer : IBingleContainer
 {
     private Dictionary<string, RegisterInfo> BingleContainerDictionary = new Dictionary<string, RegisterInfo>();
     

     /// <summary>
     /// 快取起來,型別的物件實體
     /// </summary>
     private Dictionary<Type, object> TypeObjectDictionary = new Dictionary<Type, object>();

     /// <summary>
     /// 
     /// </summary>
     /// <typeparam name="TFrom"></typeparam>
     /// <typeparam name="TTo"></typeparam>
     /// <param name="lifeTimeType">默認引數,不傳遞就是Transient</param>
     public void RegisterType<TFrom, TTo>(LifeTimeType lifeTimeType = LifeTimeType.Transient)
     {
         BingleContainerDictionary.Add(typeof(TFrom).FullName, new RegisterInfo()
         {
             TargetType = typeof(TTo),
             LifeTime = lifeTimeType
         });
     }

     public T Resolve<T>()
     {
         RegisterInfo info = BingleContainerDictionary[typeof(T).FullName];
         Type type = BingleContainerDictionary[typeof(T).FullName].TargetType;
         T result = default(T);
         switch (info.LifeTime)
         {
             case LifeTimeType.Transient:
                 result = (T)this.CreateObject(type);
                 break;
             case LifeTimeType.Singleton:
                 if (this.TypeObjectDictionary.ContainsKey(type))
                 {
                     result = (T)this.TypeObjectDictionary[type];
                 }
                 else
                 {
                     result = (T)this.CreateObject(type);
                     this.TypeObjectDictionary[type] = result;
                 }
                 break;
             case LifeTimeType.PerThread:
                 //怎么保證用執行緒校驗呢? 執行緒槽,把資料存在這里
                 {
                     string key = type.FullName;
                     object oValue =https://www.cnblogs.com/taotaozhuanyong/p/ CallContext.GetData(key);
                     if (oValue =https://www.cnblogs.com/taotaozhuanyong/p/= null)
                     {
                         result = (T)this.CreateObject(type);
                         CallContext.SetData(key, result);
                     }
                     else
                     {
                         result = (T)oValue;
                     }
                 }
                 break;
             default:
                 throw new Exception("wrong LifeTime");
         }
         return result;
     }
     private object CreateObject(Type type)
     {
         ConstructorInfo[] ctorArray = type.GetConstructors();
         ConstructorInfo ctor = null;
         if (ctorArray.Count(c => c.IsDefined(typeof(BingleInjectionConstructorAttribute), true)) > 0)
         {
             ctor = ctorArray.FirstOrDefault(c => c.IsDefined(typeof(BingleInjectionConstructorAttribute), true));
         }
         else
         {
             ctor = ctorArray.OrderByDescending(c => c.GetParameters().Length).FirstOrDefault();
         }
         List<object> paraList = new List<object>();
         foreach (var parameter in ctor.GetParameters())
         {
             Type paraType = parameter.ParameterType;
             RegisterInfo info = BingleContainerDictionary[paraType.FullName];
             Type targetType = info.TargetType;
             //object para = this.CreateObject(targetType);
             object para = null;
             #region 
                {
                    switch (info.LifeTime)
                    {
                        case LifeTimeType.Transient:
                            para = this.CreateObject(targetType);
                            break;
                        case LifeTimeType.Singleton:
                            //需要執行緒安全 雙if+lock
                            {
                                if (this.TypeObjectDictionary.ContainsKey(targetType))
                                {
                                    para = this.TypeObjectDictionary[targetType];
                                }
                                else
                                {
                                    para = this.CreateObject(targetType);
                                    this.TypeObjectDictionary[targetType] = para;
                                }
                            }
                            break;
                        case LifeTimeType.PerThread:
                            //怎么保證用執行緒校驗呢? 執行緒槽,把資料存在這里
                            {
                                string key = targetType.FullName;
                                object oValue =https://www.cnblogs.com/taotaozhuanyong/p/ CallContext.GetData(key);
                                if (oValue =https://www.cnblogs.com/taotaozhuanyong/p/= null)
                                {
                                    para = this.CreateObject(targetType);
                                    CallContext.SetData(key, para);
                                }
                                else
                                {
                                    para = oValue;
                                }
                            }
                            break;
                        default:
                            throw new Exception("wrong LifeTime");
                    }
                }
                #endregion
             //遞回:隱形的跳出條件,就是GetParameters結果為空,targetType擁有無引數建構式
             paraList.Add(para);
         }
         return Activator.CreateInstance(type, paraList.ToArray());
     }
     //屬性注入+方法注入?


 }
public class RegisterInfo
{
    /// <summary>
    /// 目標型別
    /// </summary>
    public Type TargetType { get; set; }
    /// <summary>
    /// 生命周期
    /// </summary>
    public LifeTimeType LifeTime { get; set; }
}

public enum LifeTimeType
{
    Transient,
    Singleton,
    PerThread
}
 IBingleContainer container = new BingleContainer();
 container.RegisterType<IPhone, AndroidPhone>(LifeTimeType.PerThread);
 container.RegisterType<AbstractPad, ApplePad>(LifeTimeType.PerThread);
 container.RegisterType<IHeadphone, Headphone>(LifeTimeType.Transient);
 container.RegisterType<IMicrophone, Microphone>(LifeTimeType.Singleton);
 container.RegisterType<IPower, Power>();
 container.RegisterType<IBLL.IBaseBll, BLL.BaseBll>();
 container.RegisterType<IDAL.IBaseDAL, Ruamou.DAL.BaseDAL>();
 IPhone pad1 = null;
 IPhone pad2 = null;
 IPhone pad3 = null;
 //pad1 = container.Resolve<IPhone>();
 Action act1 = new Action(() =>
 {
     pad1 = container.Resolve<IPhone>();
     Console.WriteLine($"pad1由執行緒id={Thread.CurrentThread.ManagedThreadId}");
 });
 var result1 = act1.BeginInvoke(null, null);

 Action act2 = new Action(() =>
 {
     pad2 = container.Resolve<IPhone>();
     Console.WriteLine($"pad2由執行緒id={Thread.CurrentThread.ManagedThreadId}");
 });
 var result2 = act2.BeginInvoke(t =>
 {
     pad3 = container.Resolve<IPhone>();
     Console.WriteLine($"pad3由執行緒id={Thread.CurrentThread.ManagedThreadId}");
     Console.WriteLine($"object.ReferenceEquals(pad2, pad3)={object.ReferenceEquals(pad2, pad3)}");
 }, null);

 act1.EndInvoke(result1);
 act2.EndInvoke(result2);

 Console.WriteLine($"object.ReferenceEquals(pad1, pad2)={object.ReferenceEquals(pad1, pad2)}");

 

 容器依賴細節?如果不想依賴細節,又想創建物件,反射+組態檔:

 ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
 fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config");//找組態檔的路徑
 Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
 UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);

 IUnityContainer container = new UnityContainer();
 section.Configure(container, "testContainer1");

 // container.AddNewExtension<Interception>().Configure<Interception>()
 //.SetInterceptorFor<IPhone>(new InterfaceInterceptor());

 IPhone phone = container.Resolve<IPhone>();
 phone.Call();
 IPhone android = container.Resolve<IPhone>("Android");
 android.Call();

 IDBContext<Program> context = container.Resolve<IDBContext<Program>>();
 context.DoNothing();

組態檔:

 <unity>
   <!--<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration"/>-->
   <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/>
   <containers>
     <container name="testContainer1">
       <extension type="Interception"/>
       <register type="Bingle.Interface.IPhone,Bingle.Interface" mapTo="Bingle.Service.ApplePhone, Bingle.Service"/>
       <!--是dll名稱,不是命名空間-->
       <register type="Bingle.Interface.IPhone,Bingle.Interface" mapTo="Bingle.Service.AndroidPhone, Bingle.Service" name="Android">
         <!--別名-->
         <interceptor type="InterfaceInterceptor"/>
         <interceptionBehavior type="Bingle.Framework.AOP.LogBeforeBehavior, Bingle.Framework"/>
         <interceptionBehavior type="Bingle.Framework.AOP.LogAfterBehavior, Bingle.Framework"/>
         <interceptionBehavior type="Bingle.Framework.AOP.ParameterCheckBehavior, Bingle.Framework"/>
         <lifetime type="transient" />
       </register>

       <register type="Bingle.Interface.IMicrophone, Bingle.Interface" mapTo="Bingle.Service.Microphone, Bingle.Service"/>
       <register type="Bingle.Interface.IHeadphone, Bingle.Interface" mapTo="Bingle.Service.Headphone, Bingle.Service"/>
       <register type="Bingle.Interface.IPower, Bingle.Interface" mapTo="Bingle.Service.Power, Bingle.Service"/>
       <register type="Bingle.Interface.AbstractPad, Bingle.Interface" mapTo="Bingle.Service.ApplePad, Bingle.Service"/>
       <register type="Bingle.IBLL.IBaseBll, Bingle.IBLL" mapTo="Bingle.BLL.BaseBll, Bingle.BLL">
         <constructor>
           <param name="baseDAL" type="Bingle.IDAL.IBaseDAL, Bingle.IDAL"  />
           <param name="id" type="System.Int32" value="3" />
         </constructor>
       </register>
       <register type="Bingle.IDAL.IBaseDAL, Bingle.IDAL" mapTo="Ruamou.DAL.BaseDAL, Ruamou.DAL"/>
       <register type="Bingle.IDAL.IDBContext`1, Bingle.IDAL" mapTo="Ruamou.DAL.DBContextDAL`1, Ruamou.DAL"/>
     </container>
    <unity>
View Code

 

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/12293.html

標籤:ASP.NET

上一篇:獲取支付寶授權用戶資訊

下一篇:快取cache(擦車)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more