我想编写一个静态实用程序类,它只有一组属性,向用户公开功能
例如我可以打电话:
Utils.String.GetHexString("Hello World");
或
Utils.Stream.CopyBytes(instream, outstream);
我能把它比作最接近的是System.Text.Encoding,其中有UTF8,ASCII等属性,所以你可以调用类似的东西:
Encoding.UTF8.GetBytes("Hello World");
或
Encoding.ASCII.GetBytes("Hello World");
问题在于,在编码中,这会调用用户公开可用的等效对象(UTF8Encoder
,ASCIIEncoder
)。我想要的是仅通过Utils公开对象,而不会看到与属性相关的对象,例如
我可以打电话:
Utils.Stream.CopyStream(instream, outstream);
但我无法打电话:
StreamUtils.CopyStream(instr, outstr) //This class is only accessible via the Utils class!
这是否可能,如果是这样的话,这样做是好还是坏?
答案 0 :(得分:5)
这是一个想法:
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; }
}
}
然而,对我来说,这有点奇怪。我个人更喜欢实用功能的扩展方法:
inStream.CopyStreamTo(outStream);
myString.GetHexString();
这也可以被认为是不好的,特别是考虑到扩展方法发现和解析算法。好的'StreamUtil.Copy()
对大多数情况都很好。
答案 1 :(得分:1)
无法阻止任何用户创建StreamUtils
类型的变量,例如分配从Utils.Stream
属性中检索到的值。
但是,有两种解决方案:
您可以通过制作构造函数StreamUtils
来阻止用户自己创建internal
类的实例。像这样,只有你的Utils
类(你可以通过将它放在同一个程序集中或使用InternalsVisibleTo
attribute授予内部访问权限)可以实例化你的StreamUtils
类,同时您的库的用户只能使用您的实例的功能,但不能创建自己的实例。
另一种方法是使用公共嵌套静态类。在Utils
类中,您可以声明一个嵌套的公共静态类Stream
,它提供了您需要的方法作为静态方法。像这样,用户无法实例化他们自己的Stream
实例(因为它是静态的),至少在C#中,你甚至会强迫用户总是写Utils.Stream
来访问你的方法,如果你是这样的话真的很想要。但请注意,如果您决定使用属性getter或其他任何东西来交换静态类,那么这种方法看起来并不像第一种方法那样干净并且会导致重大更改(至少在二进制级别上)。
答案 2 :(得分:0)
你想要什么是可能的,但你不应该将Utils
看作一个类本身,而应该看作包含一些静态实用程序类的命名空间:
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)
{
...
}
}
}
这是否是推荐的做法,是一个完全不同的问题。静态实用程序类太多的问题是,您不能通过使用依赖项注入来实现松散耦合。这可能会使编写好的单元测试变得更加困难。
答案 3 :(得分:0)
看看你想要实现的目标,我建议,尝试开发extention methods.
扩展方法使您可以向现有类型“添加”方法,而无需创建新的派生类型,重新编译或以其他方式修改原始类型。扩展方法是一种特殊的静态方法,但它们被称为扩展类型的实例方法。
详细了解提供的超链接here。
答案 4 :(得分:0)
好的,基本上不可能(至少在C#中)实现我想要的。该类必须是可见的,以便通过Util类可以看到该功能。
我的解决方案是将课程(例如StreamUtils
,StringUtils
)变成单身。它们不能被构造,因为它们的构造函数是内部的。他们的方法是公开的,但永远不会被看到,因为对象无法在我的程序集之外实例化。 Utils类通过单例实例向用户公开功能。
请考虑以下事项:
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;
}
}
}