|
using Microsoft.Extensions.DependencyInjection; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Collections; |
|
using System.Reflection; |
|
using System.Threading.Tasks; |
|
|
|
namespace ConsoleApp1 |
|
{ |
|
|
|
[System.AttributeUsage(AttributeTargets.Interface, Inherited = false, AllowMultiple = false)] |
|
sealed class InjectInsteadAttribute : Attribute |
|
{ |
|
// This is a named argument |
|
public Type InjectType { get; set; } |
|
} |
|
|
|
[InjectInstead(InjectType = typeof(StringDao))] |
|
public interface IDao |
|
{ |
|
List<object> GetObjects(); |
|
} |
|
|
|
public class NumberDao : IDao |
|
{ |
|
public List<object> GetObjects() |
|
{ |
|
return new List<object>() { 1, 2, 3, 4 }; |
|
} |
|
} |
|
|
|
public class StringDao : IDao |
|
{ |
|
public List<object> GetObjects() |
|
{ |
|
return new List<object>() { "hello", "world" }; |
|
} |
|
} |
|
|
|
public class CustomServiceCollection : IServiceCollection |
|
{ |
|
private readonly List<ServiceDescriptor> _descriptors = new List<ServiceDescriptor>(); |
|
|
|
/// <inheritdoc /> |
|
public int Count => _descriptors.Count; |
|
|
|
/// <inheritdoc /> |
|
public bool IsReadOnly => false; |
|
|
|
public ServiceDescriptor this[int index] |
|
{ |
|
get |
|
{ |
|
return _descriptors[index]; |
|
} |
|
set |
|
{ |
|
_descriptors[index] = value; |
|
} |
|
} |
|
|
|
/// <inheritdoc /> |
|
public void Clear() |
|
{ |
|
_descriptors.Clear(); |
|
} |
|
|
|
/// <inheritdoc /> |
|
public bool Contains(ServiceDescriptor item) |
|
{ |
|
return _descriptors.Contains(item); |
|
} |
|
|
|
/// <inheritdoc /> |
|
public void CopyTo(ServiceDescriptor[] array, int arrayIndex) |
|
{ |
|
_descriptors.CopyTo(array, arrayIndex); |
|
} |
|
|
|
/// <inheritdoc /> |
|
public bool Remove(ServiceDescriptor item) |
|
{ |
|
return _descriptors.Remove(item); |
|
} |
|
|
|
/// <inheritdoc /> |
|
public IEnumerator<ServiceDescriptor> GetEnumerator() |
|
{ |
|
return _descriptors.GetEnumerator(); |
|
} |
|
|
|
void ICollection<ServiceDescriptor>.Add(ServiceDescriptor item) |
|
{ |
|
var svcTypeInfo = item.ServiceType.GetTypeInfo(); |
|
var implTypeInfo = item.ImplementationType.GetTypeInfo(); |
|
InjectInsteadAttribute attr = svcTypeInfo.GetCustomAttribute<InjectInsteadAttribute>(); |
|
if (attr == null) |
|
{ |
|
attr = implTypeInfo.GetCustomAttribute<InjectInsteadAttribute>(); |
|
} |
|
if (attr != null) |
|
{ |
|
// we're supposed to inject something else in place of this dependency |
|
item = new ServiceDescriptor(item.ServiceType, attr.InjectType, item.Lifetime); |
|
} |
|
_descriptors.Add(item); |
|
} |
|
|
|
IEnumerator IEnumerable.GetEnumerator() |
|
{ |
|
return GetEnumerator(); |
|
} |
|
|
|
public int IndexOf(ServiceDescriptor item) |
|
{ |
|
return _descriptors.IndexOf(item); |
|
} |
|
|
|
public void Insert(int index, ServiceDescriptor item) |
|
{ |
|
_descriptors.Insert(index, item); |
|
} |
|
|
|
public void RemoveAt(int index) |
|
{ |
|
_descriptors.RemoveAt(index); |
|
} |
|
} |
|
|
|
public class App |
|
{ |
|
private readonly IServiceProvider _services; |
|
|
|
public App(IServiceProvider services) |
|
{ |
|
_services = services; |
|
} |
|
|
|
public async Task Run() |
|
{ |
|
await Task.Run(() => |
|
{ |
|
var data = _services.GetRequiredService<IDao>().GetObjects(); |
|
data.ForEach(o => Console.WriteLine(o.ToString())); |
|
}); |
|
} |
|
} |
|
|
|
public class Program |
|
{ |
|
public static void Main(string[] args) |
|
{ |
|
var services = new CustomServiceCollection(); |
|
|
|
AddDao(services); |
|
|
|
var app = new App(services.BuildServiceProvider()); |
|
|
|
app.Run(); |
|
|
|
Console.ReadLine(); |
|
} |
|
|
|
private static void AddDao(IServiceCollection services) |
|
{ |
|
services.AddTransient<IDao, NumberDao>(); |
|
} |
|
} |
|
} |