实现泛型接口的类的字典

本文关键字:字典 实现 泛型接口 | 更新日期: 2023-09-27 18:34:48

我有一个泛型接口,其中包含两个具有严格泛型约束的类型参数,以及针对不同组合的几种实现。

public interface IResolver<TIn, TOut> where ... {...}

我想创建一个(静态(解析器工厂,它将存储已知实现的实例,并按照以下行为它们提供服务:

public static ResolverFactory{
   public static IResover<TIn, TOut>  GetResolver<TIn, TOut> where ... ()
   {
       //access some storage dictionary to return the correctly typed instance
   }
}

如何创建这样一个包含器,它将存储IResover<Entity1, Entity2>IResolver<Entity3, Entity4>

我能想到的一个选择是使用单独的非通用"标记"接口,例如:

public interface IResolver {} 
public interface IResolver<TIn, TOut> : IResolver where .... 
{...}

和使用

Dictionary<Type, Dictionary <Type, IResolver>> storage;
public RegisterResolver(IResolver resolver)
{
   //add to storage - how?
}

但这种情况基本上使对泛型参数施加的约束无效。此外,在添加IResolver时,获取IResolver<TIn, TOut>的泛型类型或多或少是不可能的。

有没有更好的解决方案?

实现泛型接口的类的字典

您的问题中可能缺少一些明显的东西,因为我不明白问题出在哪里。

首先,我声明一个带有约束的IResolver<TIn, TOut>接口:

public interface IResolver<TIn, TOut>
    where TIn : Stream 
{
}

然后,我创建一个ResolverFactory,其中约束由RegisterResolverGetResolver方法强制执行。对象的实际存储方式无关紧要,因为存储不会在类外部公开。封装保持一致性:

public static class ResolverFactory
{
    private static Dictionary<Type, object> storage = new Dictionary<Type, object>();
    public static void RegisterResolver<TIn, TOut>(IResolver<TIn, TOut> resolver) where TIn : Stream 
    {
        storage[typeof(IResolver<TIn, TOut>)] = resolver;
    }
    public static IResolver<TIn, TOut> GetResolver<TIn, TOut>() where TIn : Stream
    {
        return storage[typeof(IResolver<TIn, TOut>)] as IResolver<TIn, TOut>;
    }
}

就像KooKiz的回答一样,但没有铸造,也没有字典。用法类似。

//Rather than:
var res = ResolverFactory.GetResolver<Stream, Hat>();
//You Do:
var res = ResolverFactory<Stream, Hat>.GetResolver();

只是移动了泛型参数,具有在较少位置定义泛型约束的额外优势。

public interface IResolver<TIn, TOut>
    where TIn : Stream
{
}
//Still static, but now there is one per TIn,TOut pair
//so no need for dictionary, so also no need for casting.
public static class ResolverFactory<TIn, TOut> where TIn : Stream
{
    private static IResolver<TIn, TOut> _resolver;
    public static void RegisterResolver(IResolver<TIn, TOut> resolver)
    {
        _resolver = resolver;
    }
    public static IResolver<TIn, TOut> GetResolver()
    {
        return _resolver;
    }
}

internal class Program
{
    private static void Main(string[] args)
    {
        ResolverFactory<Stream, Hat>.RegisterResolver(new MyStreamToHatResolver());
        var res = ResolverFactory<Stream, Hat>.GetResolver();
    }
}