首页 > 其他分享 >微软企业库Unity学习笔记(二)

微软企业库Unity学习笔记(二)

时间:2024-01-13 20:15:34浏览次数:29  
标签:container string 微软 description class Unity 企业库 public 构造函数

微软企业库Unity学习笔记(二)

 

接下来介绍一下依赖注入的方式:

  1. 构造函数注入
  2. 属性注入
  3. 方法注入

一、 构造函数注入

我们将介绍单构造函数和多构造函数注入

1) 单构造函数使用自动注入

  • 单构造函数自动注入,这里我们使用一个简单的例子具体类MyObject依赖于具体类MyDependentClass。
复制代码 ////具体类型的依赖关系
public class MyOjbect
{
private string description;

public string Description
{
get { return description; }
set { description = value; }
}

public MyOjbect(MyDependentClass myDependent)
{
this.Description = myDependent.Description;
}
} 复制代码 ////注入依赖
MyOjbect objlist = container.Resolve<MyOjbect>();
  • 当然除了具体类型我们还可以使用接口或者基类类型作为参数注入依赖,这里我们定义一个接口和一个抽象类。
复制代码 //// MyServiceBase是一个抽象类,然后objIMyService继承于该抽象类
//// IMyService是一个接口,objMyService实现该接口
public class MyOjbect
{
private string description;

public string Description
{
get { return description; }
set { description = value; }
}

public MyOjbect(MyServiceBase objIMyService, IMyService objMyService)
{
////TODO:
}
} 复制代码 ////注册抽象类和接口的映射关系
container.RegisterType<IMyService, MyServiceDependent>();
container.RegisterType<MyServiceBase, DataService>();

MyOjbect objlist = container.Resolve<MyOjbect>();

 

 

2) 多重载构造函数通过属性指定注入构造函数  

  通过InjectionConstructor属性指定要注入构造函数,和单构造函数功能一样,但要注意一点是当有多重载构造函数,如果我们没有使用属性指定注入构造函数,Unity会根据构造函数参数最多的进行依赖注入,如果不存在唯一最多参数的构造函数(例如:有两个或者两个以上构造函数具有最多参数时候),Unity会抛出异常。

复制代码 public class MyOjbect
{
private string description;

public string Description
{
get { return description; }
set { description = value; }
}

public MyOjbect(MyServiceBase objIMyService)
{
////
}

[InjectionConstructor]
public MyOjbect(MyServiceBase objIMyService, IMyService objMyService)
{
////
}
} 复制代码

  

  通过前面的介绍我们初步明白了Unity的作用就是给我们一个更方便实现类与类的解耦,假设在一般情况一个类依赖于其他类的时候,我们必须实例化该依赖类,然后把实例传递给我们要调用类,但有了Unity它帮我们实例了这些。OK接下来讲一个具体例子。

复制代码 /// <summary>
/// 父母类
 /// </summary>
public class Parent
{
private readonly ChildA _classA;
private readonly ChildB _classB;

public Parent() { }

//指定依赖注入构造函数
[InjectionConstructor]
public Parent(ChildA chA, ChildB chB)
{
this._classA = chA;
this._classB = chB;
}

public override string ToString()
{
// 年长的父母依赖与孩子。
return string.Format("The elder depend on {0} and {1}.", this._classA.ToString(), this._classB.ToString());
}
}
/// <summary>
/// 孩子类
/// </summary>
public class ChildA : Parent
{
public override string ToString()
{
return "ChildA";
}
}

/// <summary>
/// 孩子类
/// </summary>
public class ChildB : Parent
{
public override string ToString()
{
return "ChildB";
}
}

class Program
{
static void Main(string[] args)
{
using (IUnityContainer container = new UnityContainer())
{
Parent objParent = container.Resolve<Parent>();

Console.WriteLine(objParent.ToString());

Console.ReadKey();
}
}
} 复制代码

  

  接下通过一个简单的配置文件实例例子进一步说明,Unity是如何实现类与类之间的解耦的。

  首先我们先定义一个Foo类,它依赖于一个接口ILogger,它有两个实现分别是LoggerA和LoggerB,然后我们的Foo类要调用LoggerA。在一般情况下我们可以实例化一个LoggerA的实例,然后传递给Foo就OK了,这就是hard code给我们带来了一个紧的耦合,如果要我们修改成调用LoggerB,那么我们可以再实例化一个LoggerB对象,眼前看来是可以这样实现,但如果我们工程很大,这种做法是十分危险,当我们使用配置文件可以简单实现,来讲讲简单实现。

复制代码 static void Main(string[] args)
{
using (IUnityContainer container = new UnityContainer())
{
////Parent objParent = container.Resolve<Parent>();

////Console.WriteLine(objParent.ToString());

////Console.ReadKey();

//获取指定名称的配置节
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

//获取container名称为CfgClass下的配置
section.Containers["CfgClass"].Configure(container);

Foo myFoo = container.Resolve<Foo>();

Console.WriteLine(myFoo.ToString());

Console.ReadKey();


}
} 复制代码

App.config中的配置如下:

复制代码 <configuration>
<configSections>
<!-- 每次都必须定义的开头 -->
<section name ="unity" type ="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
Microsoft.Practices.Unity.Configuration"/>
</configSections>

<!-- 使用unity的xsd -->
<!--<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">-->
<unity>
<!-- 声明一种是用类型 -->
<typeAliases>
<typeAlias alias ="ILogger" type ="MSEnterpriseUnitity.ILogger, MSEnterpriseUnitity"/>
</typeAliases>
<containers>
<container name="CfgClass">
<!-- 设定该类型的映射关系 -->
<types>
<type type ="ILogger" mapTo="MSEnterpriseUnitity.LoggerA, MSEnterpriseUnitity" />
</types>
</container>
</containers>
</unity>
</configuration> 复制代码

二、方法注入

  当一个类的方法依赖于其他类的时候(例如构造函数参数依赖与其他类),在一般情况下通过实例化该被依赖类对象,然后将参数传递给我们依赖类的方法,如果使用方法注入可以避免实例化被依赖类对象,这里就仅仅需要在依赖方法中设置一个属性InjectionMethod就OK了。

 

2.1方法依赖于具体类

  首先我们定义两个类MyTargetOjbect和OtherObject,然后定义在MyTargetOjbect中定义一个方法Initialize(OtherObject dep),该方法的参数依赖于OtherObject类。

复制代码 /// <summary>
/// 依赖类包含一个Description和OutPut方法。
/// </summary>
public class OtherObject
{
private string _description;

public string Description
{
get { return _description; }
set { _description = value; }
}

public void OutPut()
{
Console.WriteLine(this.Description);
}
} 复制代码 复制代码 /// <summary>
/// 目标类的方法Initialize参数依赖于OtherObject类。
/// </summary>
public class MyTargetOjbect
{
public OtherObject dependentObject;
[InjectionMethod]
public void Initialize(OtherObject dep)
{
this.dependentObject = dep;
}
} 复制代码 复制代码 using (IUnityContainer container = new UnityContainer())
{
MyTargetOjbect myTargetObject = container.Resolve<MyTargetOjbect>();

myTargetObject.dependentObject.Description = "Injection successful.";
myTargetObject.dependentObject.OutPut();
} 复制代码

2.2 方法依赖于接口或者基类

  定义一个抽象类MyBaseClass,然后MyInheritBase继承该抽象类,定义一个接口IMyInterface然后ImplementInterface实现该接口。

复制代码 /// <summary>
/// 接口包含一个属性和一个方法
/// </summary>
public interface IMyInterface
{
string Description
{
get;
set;
}

void OutPut();
} 复制代码 复制代码 /// <summary>
/// 实现IMyInterface的属性和方法
/// </summary>
public class ImplementInterface : IMyInterface
{
private string _description;

#region IMyInterface 成员

public string Description
{
get
{
return _description;
}
set
{
_description = value;
}
}

public void OutPut()
{
Console.WriteLine(this.Description);
}

#endregion
} 复制代码 复制代码 /// <summary>
/// 一个抽象类包含一个属性和一个方法
/// </summary>
public abstract class MyBaseClass
{
private string _description;

public virtual string Description
{
get { return _description; }
set { _description = value; }
}
public abstract void OutPut();
} 复制代码 复制代码 /// <summary>
/// 实现抽象类的抽象方法
/// </summary>
public class MyInheritBase : MyBaseClass
{
public override void OutPut()
{
Console.WriteLine(this.Description);
}
} 复制代码 复制代码 /// <summary>
/// 目标类的方法Initialize参数依赖于OtherObject类。
/// </summary>
public class MyTargetOjbect
{
public IMyInterface myInterface;
public MyBaseClass myBase;
[InjectionMethod]
public void Initialize(IMyInterface myInterface, MyBaseClass myBase)
{
this.myInterface = myInterface;
this.myBase = myBase;
}
} 复制代码 复制代码 ////设置抽象类和接口的映射关系
container.RegisterType<MyBaseClass, MyInheritBase>();
container.RegisterType<IMyInterface, ImplementInterface>();

MyTargetOjbect myTargetObject = container.Resolve<MyTargetOjbect>();

myTargetObject.myInterface.Description = "Injection Successful.";

myTargetObject.myInterface.OutPut();

myTargetObject.myBase.Description = "Injection Successful.";

myTargetObject.myBase.OutPut(); 复制代码

三、属性注入

  当一个类的属性依赖于其他类,一般情况初始化该属性需要实例化该类型对象,然而我们可以使用Dependency属性,指定属性注入无限手动实例化类型对象。

3.1 具体类型属性

复制代码 public class MyObject
{
private SomeOtherObject _dependentObject;

[Dependency]
public SomeOtherObject DependentObject
{
get { return _dependentObject; }
set { _dependentObject = value; }
}
}

IUnityContainer uContainer = new UnityContainer();
MyObject myInstance = uContainer.Resolve<MyObject>();

// now access the property containing the dependency
SomeOtherObject depObj = myInstance.DependentObject; 复制代码

3.2抽象类或接口属性

复制代码 public class MyObject
{

private IMyInterface _interfaceObj;
private MyBaseClass _baseObj;

[Dependency]
public IMyInterface InterfaceObject
{
get { return _interfaceObj; }
set { _interfaceObj = value; }
}

[Dependency]
public MyBaseClass BaseObject
{
get { return _baseObj; }
set { _baseObj = value; }
}

}

IUnityContainer uContainer = new UnityContainer()
.RegisterType<IMyInterface, FirstObject>()
.RegisterType<MyBaseClass, SecondObject>();
MyObject myInstance = uContainer.Resolve<MyObject>();

// now access the properties containing the dependencies
IMyInterface depObjA = myInstance.InterfaceObject;
MyBaseClass depObjB = myInstance.BaseObject; 复制代码

3.3 给属性注入命名

给属性命名只需在Dependency(“name”)定义一个名字就OK了。

复制代码 public class MyTargetOjbect
{
public IMyInterface myInterface;
public MyBaseClass myBase;

private IMyInterface _MyProperty1, _MyProperty2;

//命名属性注入
[Dependency("Property2")]
public IMyInterface MyProperty2
{
get { return _MyProperty2; }
set { _MyProperty2 = value; }
}

//命名属性注入
[Dependency("Property1")]
public IMyInterface MyProperty1
{
get { return _MyProperty1; }
set { _MyProperty1 = value; }
}
} 复制代码 复制代码 //调用Property1属性注入
container.RegisterType<IMyInterface, ImplementInterface>("Property1");
//调用Property2属性注入
container.RegisterType<IMyInterface, ImplementInterface2>("Property2");

MyTargetOjbect myTargetObject = container.Resolve<MyTargetOjbect>();

IMyInterface myProperty1 = myTargetObject.MyProperty1;
IMyInterface myProperty2 = myTargetObject.MyProperty2; 复制代码

3.4 构造函数参数的属性注入

  构造函数参数依赖于其他类时候,我们可以考虑使用构造函数注入或者属性注入

复制代码 public class Foo
{
private ILogger _iLogger;

public Foo([Dependency] ILogger iLogger)
{
this._iLogger = iLogger;
}

public override string ToString()
{
return string.Format("Foo depends on {0}.", this._iLogger.ToString());
}
} 复制代码

标签:container,string,微软,description,class,Unity,企业库,public,构造函数
From: https://www.cnblogs.com/sexintercourse/p/17962841

相关文章

  • 如何让Visual Studio Tools for Unity插件用于调试你自己的Mono嵌入应用程序
       最近在测试将mono嵌入到C++应用程序中,苦于没有调试器,有时候还是不怎么方便。网上搜了一下,有VS插件MDebug、VSMonoDebugger,实际试用了一下,有点麻烦,而且似乎对Windows+VisualStudio2022支持不大好。因此想到了,Unity引擎是基于mono的,VisualStudio2022也内置了针对Unity的......
  • Unity 获取当前系统时间并在UI界面中显示
    在Unity3D中获取当前系统时间,并在UITEXT中显示 代码:usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem;usingTMPro;usingUnityEngine.UI;usingUnityEngine.SceneManagement;publicclassTIME_show:MonoBehaviou......
  • Unity3D 性能杀手Overdraw详解
    前言Unity3D是一款强大的游戏开发引擎,但在使用过程中,我们需要注意一些可能会影响游戏性能的因素。其中之一就是Overdraw(过度绘制),它可以成为性能杀手。本文将详细解释Overdraw的概念、原因以及如何通过代码实现来减少Overdraw对游戏性能的影响。对惹,这里有一个游戏开发交流小组,希......
  • DOTS Unity.Physics物理引擎碰撞查询核心分析
    最近DOTS发布了正式的版本,同时基于DOTS的理念实现了一套高性能的物理引擎,今天我们给大家分享和介绍一下这个物理引擎的碰撞查询以及核心相关概念。Unity.Physics碰撞查询概述 碰撞查询(CollisonQurey)是Unity.Physics物理引擎中的一个很重要的功能。很多游戏逻辑都需要基于碰......
  • Unity DOTS物理引擎的核心分析与详解
    最近DOTS发布了正式的版本,同时基于DOTS的理念实现了一套高性能的物理引擎,今天我们来给大家分享和介绍一下这个物理引擎的使用。Unity.Physics的设计哲学 Unity.Physics是基于DOTS设计思想的一个高性能C#物理引擎的实现,  包含了物理刚体的迭代计算与碰撞检测等查询。Unity.P......
  • Unity3D 最后一次drawcall 如何避免详解
    Unity3D是一款广泛使用的游戏开发引擎,它基于C#编程语言,可以实现跨平台的游戏开发。在Unity3D中,drawcall是一个非常重要的概念,它指的是渲染引擎每次渲染物体时所调用的函数。过多的drawcall会导致游戏性能下降,因此我们需要采取一些措施来避免过多的drawcall。对啦!这里有个游戏开发......
  • Unity3D 如何把全部游戏逻辑都放到lua层实现详解
    Unity3D是一款非常流行的游戏开发引擎,它支持C#、JavaScript和Boo等脚本语言。然而,有时候我们可能希望将全部游戏逻辑都放到Lua层实现,这样可以更方便地进行游戏逻辑的修改和调试。本文将详细介绍如何使用Unity3D将全部游戏逻辑都放到Lua层实现。对啦!这里有个游戏开发交流小组里面......
  • Unity3D 在移动端的性能优化指标怎样才算合理方面详解
    Unity3D是一款非常强大的跨平台游戏开发引擎,它能够在不同的平台上实现高质量的游戏开发。然而,在移动端上,由于硬件性能的限制,需要进行一定的性能优化才能保证游戏的流畅运行。本文将详细介绍Unity3D在移动端性能优化方面的指标和技术,并给出相关的代码实现。对啦!这里有个游戏开发交......
  • Unity3D 原始对象和占位对象详解
    Unity3D是一款强大的跨平台游戏引擎,提供了丰富的功能和工具,方便开发者创建各种类型的游戏。在Unity3D中,原始对象和占位对象是两个重要的概念。本文将详细介绍原始对象和占位对象的概念、技术详解以及代码实现。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小......
  • 在Unity中使用动捕数据实时驱动3D数字人,让3D内容创作更简单
    Unity引擎和UE引擎,是当今使用人数最多的游戏引擎软件之一,它们被广泛用于游戏开发、虚拟现实、增强现实和其他交互式3D应用程序的开发。DSFUN-Unity插件能够帮助开发者更便捷地在Unity平台中利用动捕数据进行高效创作,提升项目效率。一、插件放入当前项目文件夹下将资源包包放入unit......