面试题答案
一键面试反射机制与动态类型创建协同工作原理
- 反射获取类型信息:依赖注入框架利用反射来获取程序集中类型的元数据。在Autofac中,当注册组件时,框架通过反射获取类型的构造函数、属性等信息。例如,假设有一个接口
IUserService
及其实现类UserService
:
public interface IUserService
{
string GetUserName();
}
public class UserService : IUserService
{
public string GetUserName()
{
return "John Doe";
}
}
在Autofac中注册时,通过反射找到 UserService
的构造函数信息。
var builder = new ContainerBuilder();
builder.RegisterType<UserService>().As<IUserService>();
- 动态类型创建:基于反射获取的类型信息,框架动态创建类型的实例。当需要解析依赖时,例如在某个类中需要注入
IUserService
:
public class HomeController
{
private readonly IUserService _userService;
public HomeController(IUserService userService)
{
_userService = userService;
}
public string GetUser()
{
return _userService.GetUserName();
}
}
Autofac通过反射获取 HomeController
的构造函数,发现需要注入 IUserService
,然后根据之前注册的映射关系,利用反射动态创建 UserService
的实例,并将其注入到 HomeController
的构造函数中。
关键实现点与技术细节
- 构造函数选择:如果一个类型有多个构造函数,依赖注入框架需要选择合适的构造函数进行实例化。Autofac默认选择参数最多的构造函数。例如:
public class SomeService
{
public SomeService() { }
public SomeService(int value) { }
}
Autofac会选择 SomeService(int value)
构造函数(前提是能解析 int
类型的依赖)。如果想指定构造函数,可以使用 WithParameter
方法:
builder.RegisterType<SomeService>()
.WithParameter(new TypedParameter(typeof(int), 10));
- 属性注入:除了构造函数注入,还可以进行属性注入。例如:
public class AnotherService
{
public IUserService UserService { get; set; }
public string GetUserFromAnotherService()
{
return UserService.GetUserName();
}
}
在Autofac中启用属性注入:
builder.RegisterType<AnotherService>()
.PropertiesAutowired();
这样框架会在创建 AnotherService
实例后,通过反射设置 UserService
属性。
3. 生命周期管理:依赖注入框架还管理组件的生命周期。例如在Autofac中,可以设置组件为单例模式:
builder.RegisterType<UserService>().As<IUserService>().SingleInstance();
这意味着整个应用程序生命周期内只会创建一个 UserService
实例。框架通过反射创建实例后,会缓存该实例,后续解析依赖时直接返回缓存的实例。