C#进阶-快速了解IOC控制反转及相关框架的使用
目录
一、了解IOC
1、概念
2、生命周期
二、IOC服务示例
1、定义服务接口
2、实现服务
三、扩展-CommunityToolkit.Mvvm工具包
Messenger信使
方式一(收发消息)
方式二(收发消息)
方式三(请求消息)
一、了解IOC
IOC,即控制反转(Inversion of Control),它通过将对象的创建和管理责任从应用程序代码中转移到外部容器或框架中,实现了对象之间的松耦合和依赖性反转。
1、概念
-
依赖注入(Dependency Injection, DI):
IOC 的一种实现方式,主要通过依赖注入来实现对象之间的依赖关系,即在需要时将依赖的对象(或依赖的工厂)注入到目标对象中,而不是由目标对象自己创建。DI注入三方式:构造函数注入、属性注入、方法注入。 -
容器(Container):
IOC 容器是负责管理和注入对象的工具或框架,它可以配置、创建和组装对象,同时解决对象之间的依赖关系。常见的 IOC 容器包括 Spring Framework(Java)、Unity(C#)、Guice(Java)、Dagger(Android)等。 -
松耦合(Loose Coupling):
通过IOC,对象之间的依赖关系由外部容器来管理,使得对象之间的耦合度降低。这样,当需要改变某个对象的依赖关系时,只需调整配置,而不需要修改对象本身的代码。
2、生命周期
单例(Singleton)
单例生命周期保证在整个应用程序生命周期内只存在一个对象实例。无论有多少个请求,IOC 容器始终返回同一个实例。这种方式适合那些需要在应用程序中共享状态或资源的对象,确保了对象的唯一性和共享性。
services.AddSingleton<IApplicationService,ApplicationService>
作用域(Scoped)
作用域生命周期指定对象的生命周期与特定的作用域相关联,例如每个 HTTP 请求或每个事务。在每个作用域内,只会创建一个对象实例,并且在作用域结束时销毁。这种方式在需要限定对象生命周期到特定范围内的情况下非常有用,例如在 Web 应用中处理请求时
services.AddScoped<IApplicationService,ApplicationService>
瞬时(Transient)
瞬时生命周期意味着每次请求时都会创建一个新的对象实例。这种方式适合那些无需长时间维持状态的对象,每次请求都需要一个全新的、独立的对象实例。在 IOC 容器中,每次解析时都会创建一个新的对象。
services.AddTransient<IApplicationService,ApplicationService>
二、IOC服务示例
添加NuGet包:Microsoft.Extensions.DependencyInjection
1、定义服务接口
public interface IService
{
/// <summary>
/// 注册服务
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TObject"></typeparam>
void RegisterService<T, TObject>() where T : class where TObject : class, T;
/// <summary>
/// 获取服务
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
T AccessService<T>() where T : class;
}
2、实现服务
public class IOCService : IService
{
private static readonly Lazy<IOCService> _instance= new Lazy<IOCService>(() => new IOCService());
public static IOCService Instance=>_instance.Value;
private IOCService()
{
}
IServiceProvider serviceProvider;
ServiceCollection container = new ServiceCollection();
public void RegisterService<T, TObject>()
where T : class
where TObject : class, T
{
container.TryAddSingleton<T, TObject>(); //单例
//container.TryAddScoped<T, TObject>(); //作用域
//container.TryAddTransient<T, TObject>(); //瞬态
serviceProvider = container.BuildServiceProvider();
}
public T AccessService<T>() where T : class
{
if (serviceProvider is null)
return null;
return serviceProvider.GetService<T>();
}
}
三、扩展-CommunityToolkit.Mvvm工具包
Messenger信使
用于不同界面传输数据
方式一(收发消息)
1、创建消息
public class MyTestMessage
{
public MyTestMessage(string msg)
{
Message = msg;
}
public string Message { get; }
}
2、发布消息(某界面)
WeakReferenceMessenger.Default.Send<MyTestMessage>(new MyTestMessage(sendMsg));
3、订阅消息(其它界面)
WeakReferenceMessenger.Default.Register<MyTestMessage>(this, (r, m) =>
{
//处理接收到的消息
Message = m.Message;
});
方式二(收发消息)
1、创建消息
public class MyTestMessage
{
public MyTestMessage(string msg)
{
Message = msg;
}
public string Message { get; }
}
2、发布消息(某界面)
WeakReferenceMessenger.Default.Send<MyTestMessage>(new MyTestMessage(sendMsg));
3、订阅消息(其它界面),实现接口IRecipient<T>
public class TargetViewModel:ObservableObject,IRecipient<MyTestMessage>
{
public void Receive(MyTestMessage message)
{
//处理接收到的消息
Message = message.Message;
}
public TargetViewModel()
{
WeakReferenceMessenger.Default.Register(this);
}
private string message="Init";
public string Message
{
get => message;
set => SetProperty(ref message, value);
}
}
方式三(请求消息)
1、创建消息
public class MyTestMessage
{
public MyTestMessage(string msg)
{
Message = msg;
}
public string Message { get; }
}
public class MyRequestMessage : RequestMessage<MyTestMessage>
{
}
2、发送请求消息(某界面)
MyTestMessage reply= WeakReferenceMessenger.Default.Send<MyRequestMessage>();
MessageBox.Show(reply.Message);
3、回复消息(其它界面)
WeakReferenceMessenger.Default.Register<TargetViewModel,MyRequestMessage>(this, (r, m) =>
{
//回复
m.Reply(new MyTestMessage("ReplyMsg"));
});