参数化的通用接口 - 创建字典<类型,接口与LT; T>&GT ;? [英] Parameterize a generic interface - Create a Dictionary<Type, Interface<T>>?

查看:127
本文介绍了参数化的通用接口 - 创建字典<类型,接口与LT; T>&GT ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对不起标题是混乱的,如果我说的很对,不知道这个东西叫...随意如果你想你阅读问题后编辑它,我不知道。



我重构我的旧代码时,我注意到有很多的地方,我可以使用的策略模式。我有一个库存系统,以及项目 - 有一个以上的方式来添加一个项目 - 正常的方式,有力的方式,等你也可以交换的物品,再次用以上的方式 - 所以我想这些都是很好的地方。使用该模式。



下面是我有,加入项目:

 公共接口IAddingStrategy< T>其中T:AddArgs 
{
布尔添加(T参数);
}

公共类NormalAdd:IAddingStrategy< NormalAddArgs>
{
公共BOOL添加(NormalAddArgs参数)
{
//正常添加逻辑...
}
}

酒店的公共类ForceAdd:IAddingStrategy< ForceAddArgs>
{
公共BOOL添加(ForceAddArgs参数)
{
//力附加逻辑...
}
}

//其他策略...

公共抽象类AddArgs
{
}

公共类NormalAddArgs:AddArgs
{
公共只读参数1 P1;
公共只读参数2 P2;
等;

公共NormalAddArgs(参数1 P1,P2 param2的,等等)
{
this.p1 = P1;
this.p2 = P2;
this.etc =等;
}
}

公共类ForceAddArgs:AddArgs
{
公共参数3 P3;

公共ForceAddArgs(参数3 P3)
{
this.p3 = P3;
}
}

//其他添加ARGS ...

现在我想要做的事 - 但不知道怎么样,是:

 公共类加法
{
私人字典<类型,有事> DIC =新词典<类型,有事>();
公共加法()
{
dic.Add(typeof运算(NormalAdd),新NormalAdd());
dic.Add(typeof运算(ForceAdd),新ForceAdd());
dic.Add(typeof运算(EtcAdd),新EtcAdd());
}
}



什么都要 SOMETHING 是什么?我想这是任何加入的战略 - 但是,如果我去为 IAddingStrategy - 这是行不通的,因为它要求我指定< T> ; 参数,如果我这样做,词典无法容纳所有可能的类型的战略...;(



任何想法如何去呢?又该 SOMETHING 是?
我说得对的使用策略模式在这种情况呢?如果不是,有什么解决这个问题的最好的方法?

感谢所有您的帮助。



编辑:解决此问题的办法,将是这样的:

 公共接口IAddingStrategy 
{
无效添加(AddArgs参数);
}

酒店的公共类NormalAdd:IAddingStrategy
{
公共无效添加(AddArgs参数)
{
如果(参数是NormalAddArgs)
//正常逻辑添加到
}
}

公共类ForceAdd:IAddingStrategy
{
公共无效添加(AddArgs参数)
{
如果(参数是ForceAddArgs)
//强制添加逻辑
}
}

然后,字典,简直是<类型,IAddingStrategy>



不过说真的,我不喜欢如果的东西,它只是感觉不对 - 如果有人传递错误arg的类型?这只是在运行时检测到了,我要检测在编译时的东西。 - 使用泛型我能做到这一点。


解决方案

按我的意见:这可能是有意义的,以尽量减少对普通的曝光界面,而不需要通用参数呼叫者的链条。要做到这一点的方法之一是实现两者的通用和非通用接口



优点:




  • 您现在可以使用非通用接口的工作。

  • 合理的类型安全(在大多数情况下)。



缺点:




  • 强制类型转换,需要

  • 每方法需要两个实现。

  • 类型的安全不是由编译器保证。





  ///<总结>一些常见的基础类型< /总结> 
公共接口IAddArgs {}

///<总结>非通用接口< /总结>
公共接口IAddingStrategy
{
无效添加(IAddArgs OBJ);
}

///<总结>仿制药< /总结>
///< typeparam NAME =T>< / typeparam>
公共接口IAddingStrategy< T> :IAddingStrategy
,其中T:IAddArgs
{
无效添加(T OBJ);
}

公共类NormalAddArgs:IAddArgs {}

公共类NormalAdd:IAddingStrategy< NormalAddArgs>
{
公共无效添加(NormalAddArgs OBJ)
{

}

公共无效添加(IAddArgs OBJ)
{
添加((NormalAddArgs)OBJ);
}
}

这确实留下了如何创建唠叨问题摆在首位正确类型的参数,即什么类有足够的信息来创建 NormalAddArgs 的一个实例,以便它可以传递给相应的策略?



一种方法是要求每个类型为您创建这些类型:

  // /<总结>非通用接口< /总结> 
公共接口IAddingStrategy
{
无效添加(IAddArgs OBJ);

//背景可以提供额外的信息
IAddArgs CreateAddArgs(对象上下文)A型;
}

公共类NormalAdd:IAddingStrategy< NormalAddArgs>
{
公共无效添加(NormalAddArgs OBJ){}

公共无效添加(IAddArgs OBJ)
{
添加((NormalAddArgs)OBJ);
}

公共IAddArgs CreateAddArgs(对象上下文)
{
返回新NormalAddArgs();
}
}


Sorry the title is confusing, I don't know if I said it right, not sure what this thing is called... Feel free to edit it after you read the question if you want.

I'm refactoring my old code when I noticed there are a lot of places where I could use the Strategy pattern. I have an inventory system, and items - There are more than one ways to add an item - Normal way, forceful way, etc. You could also swap items, again, with more than one way - So I figured those are good places to use that pattern.

Here is what I have, for adding items:

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...

Now what I'm trying to do - But don't know how to, is:

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

What should SOMETHING be? I want it to be any adding strategy - But if I go for IAddingStrategy - it doesn't work since it requires me to specify the <T> parameter which if I do, the dictionary can't hold all the possible types of strategies... ;(

Any ideas how to go about this? what should SOMETHING be? Am I right of using the strategy pattern in this situation? If not, what's the best approach to this?

Thanks all for your help.

EDIT: One way around this, would be something like this:

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
    }
}

Then the dictionary would simply be <Type, IAddingStrategy>

But really, I don't like the if thing, it just doesn't feel right - what if someone passes the wrong type of arg? that is something only detected at run-time, I want to detect the thing at compile-time. - Using generics I was able to achieve that.

解决方案

Per my comments: it may make sense to minimize the exposure of the generic interface, rather than requiring generic arguments to the chain of callers. One way to do this is to implement both a generic and non-generic interface.

PROS:

  • You can now work with a non-generic interface.
  • Reasonable type safety (in most cases).

CONS:

  • Casts are required.
  • Every method needs two implementations.
  • Type safety isn't guaranteed by the compiler.

/// <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 );
    }
}

This does leave the nagging problem of how to create the correct type of arguments in the first place, i.e. what class has enough information to create an instance of NormalAddArgs so that it can be passed to the appropriate strategy?

One way is to ask each type to create these types for you:

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

这篇关于参数化的通用接口 - 创建字典&LT;类型,接口与LT; T&GT;&GT ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆