简体   繁体   English

C# 接口设计,暴露库类?

[英]C# interface design, expose library classes?

I want to define an interface "IFile" that includes an array of key/value pairs "Metadata".我想定义一个包含键/值对“元数据”数组的接口“IFile”。 When getting or setting these key/value pairs, the IFile implementor should be able to take action.在获取或设置这些键/值对时,IFile 实现者应该能够采取行动。 What would be the best way to go about this? go 关于这个问题的最佳方法是什么? I see three methods:我看到了三种方法:

Method 1) Get/Set a dictionary object:方法1)获取/设置字典object:

public interface IFile
{
    ...

    Dictionary<String, String> GetMetadata();

    void SetMetadata(Dictionary<String, String> metadata);
}

Method 2) Use a Dictionary class directly:方法2)直接使用字典class:

public interface IFile
{
    ...

    Dictionary Metadata();
}

and in the implementation of IFile, an inherited version of Dictionary could be provided that acts on get / set.并且在 IFile 的实现中,可以提供作用于 get/set 的 Dictionary 的继承版本。

Method 3) Avoid Dictionary altogether and provide a custom interface, for instance:方法3)完全避免使用Dictionary并提供自定义界面,例如:

public interface IMetadata
{
    String GetValue(String key);        
    void SetValue(String key, String value);        
    Boolean Contains(String key);        
    void Delete(String key);  

    ...
}

public interface IFile
{
    ...

    IMetadata Metadata();
}

I lean towards method 3 because it lets the implementor decide how to actually implement the metadata data structure.我倾向于方法 3,因为它让实现者决定如何实际实现元数据数据结构。 The other solutions force the use of a Dictionary.其他解决方案强制使用字典。 However method 3 seems to involve a lot of extra wrapping code.然而方法 3 似乎涉及很多额外的包装代码。

I sense that behind this question there is a deeper rooted dilemma when designing class hierarchies, which is whether to expose library classes directly or to expose a few wrapped functions that hides an internally used library class.我感觉在这个问题的背后,在设计 class 层次结构时存在一个更深层次的困境,即是直接公开库类还是公开一些隐藏内部使用的库 class 的包装函数。 I have little actual experience in making OOP designs, so advice on what the "Right Way" is in this regard would be very welcome!我在制作 OOP 设计方面几乎没有实际经验,因此非常欢迎就这方面的“正确方式”提出建议!

Thanks,谢谢,

Lars拉斯

If the type of the metadata is known at compile time, then personally I would probably go for this:如果元数据的类型在编译时已知,那么我个人可能会为此使用 go :

public interface IFile
{
    ...

    IDictionary<string, string> Metadata { get; }
}

Note - IDictionary instead of Dictionary - that leaves it up to the implementing class as to what type of dictionary implementation to use.注意- IDictionary 而不是 Dictionary - 这让实现 class 来决定使用哪种类型的字典实现。

(I used string for the dictionary type as an example and also because that's the type you used for IMetadata - change to fit your needs if necessary) (我使用字符串作为字典类型的示例,也是因为这是您用于 IMetadata 的类型 - 如有必要,请更改以适应您的需要)

ps - If the range of keys for the metadata is fixed and relatively small, then make the key an enum - that's more efficient than string comparisons. ps - 如果元数据的键范围是固定的并且相对较小,则将键设为枚举 - 这比字符串比较更有效。

I like option 3 (defining the methods in the interface), because:我喜欢选项 3(在接口中定义方法),因为:

  1. It doesn't force the implementation to use a particular data structure.它不会强制实现使用特定的数据结构。
  2. It is more testable/mock-able.它更具可测试性/可模拟性。

Method 4:方法四:

public class JFile
{
    ...

    protected Dictionary Metadata() { ... }

    ...

    // --> all this use "Dictionary" internally
    // --> but, do somthing to other "IFile" fields

    public String GetValue(String key) { ... }
    public void SetValue(String key, String value)  { ... }
    public Boolean Contains(String key)  { ... }
    public void Delete(String key)  { ... }
}

Im sorry, if It looks that I making a complicated answer.对不起,如果看起来我的答案很复杂。

I was going to suggest method 2, but...我打算建议方法2,但是...

...Since you mention that when the main object / interface "IFile", has to do some actions when a single value of the metadata changes , and the metadata items doesn't have "delegates", "events", whatever, and its a good idea to still group metadata. ...既然你提到当主要 object / 接口“IFile”,当元数据的单个值发生变化时必须执行一些操作,并且元数据项没有“代表”,“事件”,等等仍然对元数据进行分组是个好主意。

If your interface only stored the data, without performing any action when adding or deleting items, method 2 would be more practical.如果你的界面只存储数据,在添加或删除项目时不执行任何操作,方法2会更实用。

Its seems to me that you are complicated yourself, by jumping straight into interfaces.在我看来,通过直接跳入界面,您自己很复杂。 I suggest:我建议:

  1. make a full demo working class MyClass制作一个完整的演示 class MyClass
  2. make an abstract superclass with all the same method, class MyClass: MySuperClass, with a working demo.用所有相同的方法创建一个抽象超类,class MyClass: MySuperClass,带有一个工作演示。
  3. Take the abstract superclass, and design an interface based from that superclass获取抽象超类,并基于该超类设计一个接口

There is a "better way", but "right, perfect, way" doesn't not exists in Software Development, because its too much complex, to have a single way to do things.有一种“更好的方式”,但“正确、完美的方式”在软件开发中并不存在,因为它太复杂了,没有单一的方式来做事。 Even if you pick another method, if it works, well, then it works.即使您选择另一种方法,如果它有效,那么它也有效。

Good Luck;-)祝你好运;-)

Why not use IDictionary if your concern is forcing inheritance off dictionary in the key value pair dictionary?如果您担心在键值对字典中强制 inheritance 关闭字典,为什么不使用 IDictionary?

then your first approach kind of works.那么你的第一种方法很有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM