我正在尝试制作自定义配置解决方案,并且需要能够添加临时服务,但当我不知道类型时,我无法弄清楚如何引用通用元素。
我添加了一个 Transient 类型的元素,它采用多个 TransientItem 元素。 后来我不想迭代这些项目并将它们添加到服务集合中。
听起来很简单,但我一定错过了一些东西。
public interface ITransient : IAppFeatureBase
{
IEnumerable<TransientItem<????>> Get();
}
public sealed class Transient : AppFeatureBase, ITransient
{
private readonly ICollection<TransientItem<????>> _items = new Collection<TransientItem<?????>>();
public Transient(params TransientItem<?????>[] items) : base(Features.Transient)
{
_items.AddRange(_items);
}
public IEnumerable<TransientItem<????>> Get() => _items;
}
public struct TransientItem<TEntity> where TEntity : class
{
public readonly IServiceCollection Add(IServiceCollection services) => services.AddTransient<TEntity>();
}
public struct TransientItem<TInterface, TEntity> where TInterface : class
where TEntity : class, TInterface
{
public readonly IServiceCollection Add(IServiceCollection services) => services.AddTransient<TInterface, TEntity>();
}
这是我配置服务的地方:
foreach(Transient trans in features.Where(feat => feat.Type == Features.Transient))
{
foreach(TransientItem<????> item in trans.Get())
{
item.Add(builder.Services);
}
}
谢谢!
底线是你不能做你所要求的事情,因为除非类是通用的,否则构造函数不能添加通用元素。
但是,根据评论,听起来您只是想创建一个 DI 容器,您可以将一个具体实例注册到一个接口,并在另一段代码中根据该接口拉出该具体实例。
这是我为此编写的代码:
public sealed class Registry
{
private readonly Dictionary<Type, object> _items = new Dictionary<Type, object>();
public void Register<I>(I instance)
{
_items[typeof(I)] = instance;
}
public I Resolve<I>() => (I)_items[typeof(I)];
public bool TryResolve<I>(out I instance)
{
if (_items.ContainsKey(typeof(I)))
{
instance = (I)_items[typeof(I)];
return true;
}
instance = default(I);
return false;
}
}
所以,现在,我有了这些接口和类:
public interface IFoo { }
public class Foo : IFoo { }
public interface IBar { }
public class Bar : IBar { }
我可以这样使用它们:
var registry = new Registry();
registry.Register<IFoo>(new Foo());
registry.Register<IBar>(new Bar());
/* somewhere else in the code */
IFoo foo = registry.Resolve<IFoo>();
if (registry.TryResolve<IBar>(out IBar bar))
{
/* do something with `bar` */
}