参数化通用接口 - 创建一个Dictionary <type,interface <t =“”>&gt;?</type,>

时间:2013-11-20 00:12:14

标签: c# generics interface strategy-pattern

很抱歉这个标题令人困惑,我不知道我说的是不对,不知道这个叫什么东西......如果你想要的话,请在阅读问题后随意编辑。

当我注意到有很多地方可以使用策略模式时,我正在重构我的旧代码。我有一个库存系统和物品 - 有多种方法可以添加物品 - 正常方式,有力的方式等等。您还可以使用多种方式再次交换物品 - 所以我认为这些是很好的地方使用那种模式。

以下是添加项目的内容:

public interface IAddingStrategy<T> where T : AddArgs
{
    bool Add(T args);
}

public class NormalAdd : IAddingStrategy<NormalAddArgs>
{
    public bool Add(NormalAddArgs args)
    {
        // normal adding logic...
    }
}

public class ForceAdd : IAddingStrategy<ForceAddArgs>
{
    public bool Add(ForceAddArgs args)
    {
        // force adding logic...
    }
}

// other strategies...

public abstract class AddArgs
{
}

public class NormalAddArgs : AddArgs
{
    public readonly param1 p1;
    public readonly param2 p2;
    etc;

    public NormalAddArgs(param1 p1, param2 p2, etc)
    {
        this.p1 = p1;
        this.p2 = p2;
        this.etc = etc;
    }
}

public class ForceAddArgs : AddArgs
{
    public param3 p3;

    public ForceAddArgs(param3 p3)
    {
        this.p3 = p3;
    }
}

// other adding args...

现在我正在尝试做什么 - 但不知道怎么做,是:

public class Adder
{
    private Dictionary<Type, SOMETHING> dic = new Dictionary<Type, SOMETHING>();
    public Adder()
    {
        dic.Add(typeof(NormalAdd), new NormalAdd());
        dic.Add(typeof(ForceAdd), new ForceAdd());
        dic.Add(typeof(EtcAdd), new EtcAdd());
    }
}

SOMETHING应该是什么?我希望它是任何添加策略 - 但如果我选择IAddingStrategy - 它不起作用,因为它要求我指定<T>参数,如果我这样做,字典不能保持所有可能的战略类型......;(

任何想法如何解决这个问题? SOMETHING应该是什么? 在这种情况下,我是否正确使用策略模式?如果没有,最好的方法是什么?

感谢大家的帮助。

编辑:解决这个问题的方法是:

public interface IAddingStrategy
{
    void Add(AddArgs args);
}

public class NormalAdd: IAddingStrategy
{
    public void Add(AddArgs args)
    {
        if (args is NormalAddArgs)
            // normal add logic
    }
}

public class ForceAdd: IAddingStrategy
{
    public void Add(AddArgs args)
    {
        if (args is ForceAddArgs)
            // force add logic
    }
}

然后字典只是<Type, IAddingStrategy>

但实际上,我不喜欢if这个东西,它只是感觉不对 - 如果有人通过错误类型的arg会怎么样?这是在运行时才检测到的东西,我想在编译时检测到这个东西。 - 使用泛型我能够实现这一点。

2 个答案:

答案 0 :(得分:1)

根据我的评论:最小化通用接口的暴露可能是有意义的,而不是要求调用者链的泛型参数。一种方法是实现通用和非通用接口。

优点:

  • 您现在可以使用非通用界面。
  • 合理的类型安全(大多数情况下)。

缺点:

  • 需要施放。
  • 每个方法都需要两个实现。
  • 编译器无法保证类型安全。
/// <summary>Some common base type.</summary>
public interface IAddArgs {}

/// <summary>Non-generic interface.</summary>
public interface IAddingStrategy
{
    void Add( IAddArgs obj );
}

/// <summary>Generic version.</summary>
/// <typeparam name="T"></typeparam>
public interface IAddingStrategy<T> : IAddingStrategy
    where T : IAddArgs
{
    void Add( T obj );
}

public class NormalAddArgs : IAddArgs {}

public class NormalAdd : IAddingStrategy<NormalAddArgs>
{
    public void Add( NormalAddArgs obj )
    {

    }

    public void Add( IAddArgs obj )
    {
        Add( (NormalAddArgs)obj );
    }
}

这确实留下了如何创建正确类型的参数的唠叨问题,即哪个类有足够的信息来创建NormalAddArgs的实例,以便可以将其传递给适当的策略?

一种方法是让每种类型为您创建这些类型:

/// <summary>Non-generic interface.</summary>
public interface IAddingStrategy
{
    void Add( IAddArgs obj );

    // "context" can be a type that provides additional info
    IAddArgs CreateAddArgs( object context );
}

public class NormalAdd : IAddingStrategy<NormalAddArgs>
{
    public void Add( NormalAddArgs obj ) { }

    public void Add( IAddArgs obj )
    {
        Add( (NormalAddArgs)obj );
    }

    public IAddArgs CreateAddArgs( object context )
    {
        return new NormalAddArgs();
    }
}

答案 1 :(得分:0)

我不认为您的案例中会有Dictionary<Type, Interface<T>>,因为您需要将T定义为词典中所有值的共同点。

Jon Skeet对类似的问题给出了很好的答案:Generic Dictionary with a value as a Interface with a Generic reference。我希望它对你也有所帮助。