As far as I can tell, this type of construct isn't a usual C# idiom, but I'm trying to emulate the interface of an existing API as closely as possible.
My initial idea was to have a public instance of a private nested class; however, this gives an error about inconsistent accessibility. This makes sense to some extent, the consumer needs to see the class definition in order to know what methods are available to be called.
I'd like for the library to be usable through the following interface:
Web3 web3 = new Web3(new HttpProvider("hostname"));
string apiVersion = web3.Version.Api;
string transactionResponse = Web3.Eth.SendTransaction(transaction);
This type of interface is par for the course in Ruby or JavaScript, just having a hard time figuring out what the C# equivalent would be.
Portions of the nested classes would depend on the specific instantiation of Web3 (they depend on information retrieved from the specific RPC node connected to)
My first thought to implement this looked like:
public class Web3
{
public readonly VersionInfo Version;
private class VersionInfo
{
public readonly string Api = "2.0";
}
}
Of course, this gives the inconsistent accessibility error.
A standalone class with internal visibility does not work for the same reason.
Is there any way to do this? Create a class that's instantiated with the outer class, but can't be instantiated on it's own?
One approach is to make the class private entirely, and return an interface:
private class VersionInfo : IVersionInfo
{
public string Api { get { return "2.0"; } }
}
public interface IVersionInfo
{
string Api { get; }
}
And then just change your definition in Web3
from VersionInfo
to IVersionInfo
.
Alternatively, you could just make it so that the class can't** be instantiated or extended outside the library:
// Sealed to stop it being extended
public sealed class VersionInfo
{
// Internal to stop it being instantiated outside the library
internal VersionInfo()
{
}
public readonly string Api = "2.0";
}
** I say can't, but a determined person can create an instance using reflection. This isn't something you can prevent, however.