2

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

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>

有没有更好的解决方案?

4

2 回答 2

3

There may be something obvious I'm missing in your question, because I don't understand where the issue is.

First, I declare a IResolver<TIn, TOut> interface with a constraint:

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

}

Then, I create a ResolverFactory, where the constraints are enforced by both the RegisterResolver and GetResolver method. The way the objects are actually stored doesn't matter, because the storage isn't exposed outside of the class. The encapsulation maintains the consistency:

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>;
    }
}
于 2013-10-10T12:18:28.143 回答
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();
    }
}
于 2013-10-10T12:40:26.130 回答