I'm sure this must be a common problem. I've got a class that in an ideal world would have the following constructors
public Thing(string connectionString)
public Thing(string fileName)
Obviously this isn't allowed because the signatures are the same. Does anybody know of an elegant solution to this problem?
You can used the named constructor idiom:
public class Thing
{
private string connectionString;
private string filename;
private Thing()
{
/* Make this private to clear things up */
}
public static Thing WithConnection(string connectionString)
{
var thing = new Thing();
thing.connectionString = connectionString;
return thing;
}
public static Thing WithFilename(string filename)
{
var thing = new Thing();
thing.filename = filename;
return thing;
}
}
Well, there are several potentials - what's considered elegent depends on the usage scenario.
Static factory methods, that call into a private constructor.
static Thing thingWithFileName(string fileName)
Create a different type for one of the parameters, or use a builtin. Rather than a string fileName, you could use a System.IO.FileStream. This is also more type safe, as I can't accidently pass the wrong data into the wrong static method, or field.
Pass a second parameter to the constructor, either an enum or a boolean, indicating the intent of the first parameter
enum ThingType { FileName, ConnectionString }
Thing(string str, ThingType type) ...
Subclass Thing, so you have a ConnectionTypeThing and a FileBackedThing
Completely eliminate Thing doing it's connection, and have preconnected data sources provided. So you end up with
Thing(InputStream dataSource)
or something analogous.
My "elegance" money goes on either the first or second suggestions, but I'd need more context to be happy with any choice.
You can make all the constructors private and create factory methods (static methods on the class like CreateFromConnectionString()).
These actually seem like different "things" to me, either a class associated with a file or a class associated with a database. I'd define an interface, then have separate implementations for each. Use a Factory to generate the correct implementation.
A hint that you may need to change your design is if your methods have to decide whether they are working with a file or a database before they perform the required action. If this is the case, then separating into different classes would be the way I would go.
public interface IThing
{
... methods to do the things that Things do
}
public class FileThing : IThing
{
... file-based methods
}
public class DatabaseThing : IThing
{
... database-based methods
}
public static class ThingFactory
{
public IThing GetFileThing( string name )
{
return new FileThing( name );
}
public IThing GetDatabaseThing( string connectionString )
{
return new DatabaseThing( connectionString );
}
}
If you had common behavior you could alternatively define an abstract class containing the default/common behavior and derive from it instead of/in addition to the interface.
Make two public properties ConnectionString and FileName and then use these to fill your object.
In C# you can use an object initalizer. Like this:
Thing thing = new Thing{FileName = "abc", ConnectionString = "123"};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With