如果无法定义类型,如何引用泛型对象

问题描述 投票:0回答:1

我正在尝试制作自定义配置解决方案,并且需要能够添加临时服务,但当我不知道类型时,我无法弄清楚如何引用通用元素。

我添加了一个 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);
    }
}

谢谢!

c# asp.net-core generics
1个回答
0
投票

底线是你不能做你所要求的事情,因为除非类是通用的,否则构造函数不能添加通用元素。

但是,根据评论,听起来您只是想创建一个 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` */
}
© www.soinside.com 2019 - 2024. All rights reserved.