实现通用接口的类的字典

时间:2013-10-10 11:53:21

标签: c# generics factory

我有一个通用接口,带有两个具有严格通用约束的类型参数,以及几种不同组合的实现。

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>的泛型类型或多或少是不可能的。

有更好的解决方案吗?

2 个答案:

答案 0 :(得分:3)

在你的问题中可能有一些显而易见的东西,因为我不明白问题出在哪里。

首先,我声明一个带有约束的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>;
    }
}

答案 1 :(得分:2)

像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();
    }
}