Question

I want to write a static utility class which only has a set of properties, which expose functionality to the user

For example I could call:

Utils.String.GetHexString("Hello World");

or

Utils.Stream.CopyBytes(instream, outstream);

The closest thing I could liken this to is System.Text.Encoding where there are properties like UTF8, ASCII etc, so yo can call things like:

Encoding.UTF8.GetBytes("Hello World");

or

Encoding.ASCII.GetBytes("Hello World");

The problem is that in Encoding, this calls the equivalent objects (UTF8Encoder, ASCIIEncoder) which are publicly available to the user. What I want is to expose the objects ONLY via Utils, without visibilty of the objects that relate to the properties, for example

I could call:

Utils.Stream.CopyStream(instream, outstream);

but I could not call:

StreamUtils.CopyStream(instr, outstr) //This class is only accessible via the Utils class!

Is this possible, and if it is, is it going to be good or bad practice to do so?

Was it helpful?

Solution 5

Ok, basically it's no possible (in C# at least) to achieve exactly what I want. The class must be visible for the functionality to be visible through the Util class.

My solution was to turn the classes (e.g. StreamUtils, StringUtils) into singletons. They cannot be constructed because their constructors are internal. their methods are public but can never be seen because the object cannot be instantiated outside of my assembly. The Utils class exposes the functionality to the user via the singleton instance.

Consider the following:

class StreamUtils
{
    static StreamUtils instance;

    internal static StreamUtils Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new StreamUtils();
            }
            return instance;
        }
    }

    internal StreamUtils()
    {
    }

    public void CopyStream(Stream input, Stream output)
    {
    }
}

static class Utils
{
    public StreamUtils Stream
    {
        get
        {
             return StreamUtils.Instance;
        }
    }
}

OTHER TIPS

Here's an idea:

public interface IStreamUtil
{
    void CopyStream(Stream int, Stream out);
}

internal class StreamUtil : IStreamUtil
{
    // Implementation
}

public static class Util
{
    private static IStreamUtil stream = new StreamUtil();
    public static IStreamUtil Stream 
    {
        get { return stream; }
    }
}

To me, however, this is somewhat of a strange practice. Personally I prefer extension methods for utility functionality:

inStream.CopyStreamTo(outStream);
myString.GetHexString();

which can also be considered bad, especially taking into account extension method discovery and resolution algorithms. Good ol' StreamUtil.Copy() is just fine for most cases.

It is not possible to prevent any user from creating a variable of your StreamUtils type and e.g. assigning the value retrieved from your Utils.Stream property.

However, there are two solutions:

  1. You can prevent users from creating instances of your StreamUtils class themselves by making the constructor internal. Like that, only your Utils class (to which you can grant internal access, be it by placing it in the same assembly or by using the InternalsVisibleTo attribute) can instantiate your StreamUtils class, while users of your library can only use the functions of your instance, but cannot create their own instance.

  2. Another approach is using public nested static classes. Within your Utils class, you could declare a nested public static class Stream that offers the methods you need as static methods. Like this, users could not instantiate their own Stream instance (as it's static), and at least in C#, you would even force users to always write Utils.Stream to access your methods, if that is what you really want. Note, however, that this approach does not seem as clean as the first one and will cause breaking changes (at least on the binary level), should you ever decide to exchange the static classes with property getters or anything else.

What you want is possible, but you shouldn't see Utils as a class itself, but as a namespace that contains some static utility classes:

namespace Utils
{
    public static class String
    {
        public static string GetHexString(string input)
        {
            ...
        }
    }

    public static class Stream
    {
        public static void CopyBytes(System.IO.Stream instream, System.IO.Stream outstream)
        {
            ...
        }
    }
}

Whether this is a recommended practice or not, is a completely different issue. The problem with too many static utility classes, is that you can't have loose coupling by using dependency injection. This can make it harder to write good unit tests.

Looking at what you are trying to achieve, I suggest, try and develop extention methods.

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type.

Read more on the hyperlink provided here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top