根据 Microsoft.Extensions.DepdencyInjection 框架简单仿写的一个 DI 框架。
官方地址:https://github.com/dotnet/runtime/tree/main/src/libraries/Microsoft.Extensions.DependencyInjection
测试示例;
using MyDI.Core;
ServiceCollection sc = new ServiceCollection();
sc.AddScoped<IPerson, Student>();
sc.AddSingleton<Student>(new Student("A"));
var provider = sc.Build();
var student = provider.GetService<IPerson>();
student.Say();
var studentA = provider.GetService<Student>();
studentA.Say();
/*
* output :
* Ani is a student.
* A is a student.
*/
#region Test Cases
public interface IPerson
{
public void Say();
}
class Student : IPerson
{
public Student()
{
}
public Student(string name)
{
Name = name;
}
public string Name { get; } = "Ani";
public void Say()
{
Console.WriteLine($"{Name} is a student.");
}
}
#endregion
框架核心代码:
using System.Collections.ObjectModel;
namespace MyDI.Core;
#region Core
public interface IServiceProviderBuilder
{
public IServiceProvider Build();
}
public class ServiceCollection : Collection<ServiceDescription>, IServiceProviderBuilder
{
/// <inheritdoc />
public IServiceProvider Build()
{
return new ServiceProvider(this);
}
}
public static class ServiceCollectionExtensions
{
public static void AddScoped<T, I>(this ServiceCollection serviceCollection) => serviceCollection.Add(new ServiceDescription(typeof(T), typeof(I)));
public static void AddSingleton<T>(this ServiceCollection serviceCollection, object? value) => serviceCollection.Add(new ServiceDescription(typeof(T), value?.GetType(), value));
}
public class ServiceProvider : IServiceProvider
{
private ServiceCollection _serviceCollection;
public ServiceProvider(ServiceCollection serviceCollection)
{
_serviceCollection = serviceCollection;
}
/// <inheritdoc />
public object? GetService(Type serviceType)
{
var description = _serviceCollection.FirstOrDefault(t => t.ServiceType == serviceType);
switch (description)
{
case null:
throw new InvalidOperationException("please register the service type.");
case { Value: not null }:
return description.Value;
}
var implementType = description.ImplementType;
var constructorInfos = implementType?.GetConstructors();
var len = constructorInfos?.Length;
if (constructorInfos == null || len == 0)
{
throw new InvalidOperationException("please provide at least one public constructor.");
}
else if (len == 1)
{
var constructorInfo = constructorInfos[0];
var result = constructorInfo.Invoke(null);
description.Value = result;
return result;
}
var paraments = description.Paraments;
var paramentsLength = paraments?.Length;
var constructorInfoT = constructorInfos.FirstOrDefault(t => t.GetParameters().Length == paramentsLength);
if (constructorInfoT == null)
{
constructorInfoT = constructorInfos.FirstOrDefault(t => t.GetParameters().Length == 0);
}
if (constructorInfoT == null)
throw new InvalidCastException("not matched for best constructor.");
var value = constructorInfoT?.Invoke(paraments);
description.Value = value;
return value;
}
}
public static class ServiceProviderExtensions
{
public static T GetService<T>(this IServiceProvider provider)
{
var result = (T)provider.GetService(typeof(T))!;
return result;
}
}
public class ServiceDescription
{
public ServiceDescription()
{
}
public ServiceDescription(Type serviceType, Type? implementType)
{
ServiceType = serviceType;
ImplementType = implementType;
}
public ServiceDescription(Type serviceType, Type? implementType, object? value)
{
ServiceType = serviceType;
ImplementType = implementType;
Value = value;
}
public ServiceDescription(Type serviceType, Type? implementType, object[] paraments, object? value)
{
ServiceType = serviceType;
ImplementType = implementType;
Paraments = paraments;
Value = value;
}
public Type ServiceType { get; set; }
public Type? ImplementType { get; set; }
public object[] Paraments { get; set; } = Array.Empty<object>();
public object? Value { get; set; }
public ServiceScope ServiceScope { get; set; }
}
public class ServiceScope
{
}
#endregion
标签:框架,serviceCollection,value,public,var,new,Net,Type,Core7
From: https://www.cnblogs.com/fires/p/17502618.html