简体   繁体   中英

C# interface design, expose library classes?

I want to define an interface "IFile" that includes an array of key/value pairs "Metadata". When getting or setting these key/value pairs, the IFile implementor should be able to take action. What would be the best way to go about this? I see three methods:

Method 1) Get/Set a dictionary object:

public interface IFile
{
    ...

    Dictionary<String, String> GetMetadata();

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

Method 2) Use a Dictionary class directly:

public interface IFile
{
    ...

    Dictionary Metadata();
}

and in the implementation of IFile, an inherited version of Dictionary could be provided that acts on get / set.

Method 3) Avoid Dictionary altogether and provide a custom interface, for instance:

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. The other solutions force the use of a Dictionary. However method 3 seems to involve a lot of extra wrapping code.

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. I have little actual experience in making OOP designs, so advice on what the "Right Way" is in this regard would be very welcome!

Thanks,

Lars

If the type of the metadata is known at compile time, then personally I would probably go for this:

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.

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

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.

I like option 3 (defining the methods in the interface), because:

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

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

If your interface only stored the data, without performing any action when adding or deleting items, method 2 would be more practical.

Its seems to me that you are complicated yourself, by jumping straight into interfaces. I suggest:

  1. make a full demo working class MyClass
  2. make an abstract superclass with all the same method, class MyClass: MySuperClass, with a working demo.
  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?

then your first approach kind of works.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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