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"};
Here are some workarounds.
Have one constructor that takes a connection string, and then have a factory method on the class that takes filename. Something like this:
public static Thing CreateThing(string fileName)
this method can call a private parameter less constructor, and you can take it from there.
Another option, is to have an enum that has two types in it. FileName and ConnectionString. Then just have one constructor that takes a string, and the enum. Then based on the enum you can determine which way to go.
I like static constructor-functions:
class Thing
{
public static Thing NewConnection(string connectionString)
{
return new Thing(connectionString, true);
}
public static Thing NewFile(string fileName);
{
return new Thing(fileName, false);
}
}
.
.
.
{
var myObj = Thing.NewConnection("connect=foo");
var Obj2 = Thing.NewFile("myFile.txt");
}
(not shown, but straight-forward, the implementation of the Thing-Constructor with an extra boolean parameter).
Related
This is stripped down from a more complex situation.
The goal is to construct several instances of class SubAction, each of which uses an action to alter how it uses its internal data.
Consider:
public class SubAction
{
private Action<SubAction> _DoIt;
public SubAction(Action<SubAction> doIt)
{
_DoIt = doIt;
}
public void DoIt()
{
_DoIt(this);
}
static public Action<SubAction> GetAction1 => (it) => it.DoSomething(it._Data.Value1);
static public Action<SubAction> GetAction2 => (it) => it.DoSomething(it._Data.Value2);
private void DoSomething(string value)
{
// ...
}
// This gets set by code not shown.
protected Data _Data;
}
public class Data
{
public string Value1;
public string Value2;
}
public class SubActionTests
{
static SubActionTests()
{
var actions = new List<SubAction>
{
new SubAction(SubAction.GetAction1),
new SubAction(SubAction.GetAction2),
};
// ... code not shown that calls a method to update each instance's _Data...
foreach (var subAction in actions)
{
subAction.DoIt();
}
}
}
This works, but it seems cumbersome. Specifically:
public Action<SubAction> _DoIt { get; set; }
...
static public Action<SubAction> GetAction1 => (it) => it.DoSomething(it._Data.Value1);
...
new SubAction(SubAction.GetAction1)
If I set DoIt AFTER constructing the object, could simply be:
public Action DoIt { get; set; }
...
public Action GetAction1 => () => DoSomething(_Data.Value1);
...
var it = new SubAction();
it.DoIt = it.GetAction1;
Which has simpler action declarations:
The actions don't need <SubAction>.
`GetAction1,2,3.. declarations are much simpler.
But more verbose instance initialization, because access to it is needed to set DoIt.
Unfortunately it isn't possible to refer to "it" during object initializer, so there doesn't seem to be any way to have BOTH the simpler initialization syntax AND the simpler action-declaration syntax.
Am I overlooking some solution?
ALTERNATIVE: factory method
NOTE: This could be approached quite differently, by using an enum to select between the different actions. But that is a different sort of complication; I'm looking for a way to describe these Actions themselves more succinctly.
Specifically, I'm aware there could be a factory method that takes an enum, to hide the complexity:
public enum WhichAction
{
Action1,
Action2
}
...
public static CreateSubAction(WhichAction which)
{
var it = new SubAction();
switch (which)
{
case WhichAction.Action1:
it.DoIt = it.GetAction1;
break;
case WhichAction.Action2:
it.DoIt = it.GetAction2;
break;
}
return it;
}
The downside of this is that each added action requires editing in multiple places.
ALTERNATIVE: sub-classes
Another alternative is to create multiple sub-classes.
That is what I was doing originally, but that was even more verbose - multiple lines per each new action.
And felt like "overkill".
After all, the approach I've got isn't terrible - its a single line for each new GetAction. It just felt like each of those lines "ought" to be much simpler.
Sadly, from what I understand, I don't think you can make the complexity disappear. You probably need to choose an approach from the ones you suggested (or even other solutions like using a strategy pattern).
Advice
When confronted with a design choice like this. I suggest you optimize for the consumer's side of things. In other words, design your classes to make them simple to use.
In your scenario, that would mean opting for your initial solution or the more complex solutions (factory method, sub-classes, strategy pattern, etc.).
The problem with the second solution is that your object can be in a limbo state when initializing it.
var it = new SubAction();
// Before you set DoIt, the object is not fully initialized.
it.DoIt = it.GetAction1;
Consumers can also forget to set DoIt. When possible, you should probably avoid designs that allow such mistakes.
While I'm still curious whether there are syntax alternatives that would streamline what I showed, so I'll accept an answer that shows a simpler syntax, turns out in my situation, I can easily avoid the need for those actions.
Discussing with a colleague, they pointed out that my current actions all have a similar pattern: get a string, pass it to SubAction.DoSomething.
Therefore I can simplify those actions down to a property that gets the appropriate string:
public abstract string CurrentValue { get; }
...
public virtual void DoIt()
{
DoSomething(CurrentValue);
}
Given the above, subclasses become so simple they no longer feel like "overkill":
public class SubAction1 : SubAction
{
protected override string CurrentValue => _Data.Value1;
}
...
// usage
new SubAction1()
That is straightforward; highly readable. And trivial to extend when additional conditions are needed.
There will be more complicated situations that do need to override DoSomething. In those, the "real work" dwarfs what I've shown; so its appropriate to subclass those anyway.
I have an Address class:
public class Address
{
//Some stuff
}
and there's a corresponding *Wrapper class to enforce certain rules on how to
use the Address class:
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
where IWrapped is defined as:
public interface IWrapped<T>
{
T GetWrapped();
}
I have the following generic class for saving these entities (there are other
entities that follow this pattern of Entity and EntityWrapper):
public class GenericRepository
{
private GenericRepository() { }
public static void Add<T>(IWrapped<T> entity)
{
//Do something
}
public static void AddList<T>(IList<IWrapped<T>> entities)
{
//Do something
}
}
and I have this test code:
[Test]
public void UseGenericRepository()
{
AddressWrapper addrW = new AddressWrapper();
addrW.AddrLine1 = "x";
addrW.AddrLine2 = "y";
addrW.AddrLine3 = "z";
addrW.City = "Starling City";
//This works as expected
GenericRepository.Add<Address>(addrW);
IList<AddressWrapper> addrList = new List<AddressWrapper>();
//Fill up the addrList
//This gives error: best overloaded method match has some invalid
//arguments
GenericRepository.AddList<Address>(addrList);
}
AddressWrapped is of type IWrapped<Address> (i.e., it implements it) and
Address is the type parameter being given to the AddList method, so the
types should line up. I know that this is due to my limited knowledge of C#
generics (familiar with Java generics), but can't figure out what's wrong here
--- it should work.
This probably doesn't make any difference, but here's my config:
NHibernate 4.x
.NET Framework (4.5)
This is because of the missing type variance of IList<T>. (IList<int> is not an IList<object>).
Use IEnumerable<T>, because it is covariant:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do something
}
Reason: If you get an instance of List<AddressWrapper>, the compiler doesn't know if it is compatible with any possible implementation of IList<IWrapped<T>>. Assume another class that implements IWrapped<T>. It wouldn't be compatible when writing to the List. Even though you don't write to the list in AddList, the compiler only accepts compatible types. IEnumerable<T> cannot be written, so it can be variant.
Not related to the question I suggest to use covariance for your own interface as well:
public interface IWrapped<out T>
to make IWrapped<Thing> compatible with IWrapped<SpecificThing>.
MSDN: https://msdn.microsoft.com/en-us/library/ee207183.aspx
To make this clear by an example. Would would you expect happen if we had two types implement IWrapped<T>?
public class AddressWrapper : IWrapped<Address>
{
private Address _wrapped;
public Address GetWrapped()
{
return _wrapped;
}
//And some more
}
public class OtherWrapper : IWrapped<MailBox>
{
public MailBox GetWrapped()
{
throw new MailBox();
}
}
And we tried to add them to a third list inside AddList<T>:
public static void AddList<T>(IList<IWrapped<T>> entities)
{
internalList = new List<IWrapped<T>>();
list.AddRange(entities); // BOOM.
}
The type system is keeping you from making a mistake. List<T> isn't covariant exactly for that reason.
At the point at which you're trying to call AddList(), for all the compiler knows, that method may add objects of any type that implements IWrapper<Address> (i.e. types that aren't AddressWrapper) to the passed in list.
That would be bad because the list you're trying to pass to the method doesn't want to contain anything other than AddressWrappers.
NB: Please see the answer by #StefanSteinegger, it is especially enlightening.
What worked for me was changing the way I was defining addrList, from:
IList<AddressWrapper> addrList = new List<AddressWrapper>();
to:
IList<IWrapped<Address>> addrList = new List<IWrapped<Address>>();
However, I am also changing the signature of the GenericRepository.AddList<T>(..) method to take an IEnumerable as that also helps indicate that the input is read-only. So:
public static void AddList<T>(IEnumerable<IWrapped<T>> entities)
{
//Do some stuff
}
My guess until now was that a dynamic type just "switches off" type checking during compilation and does something similar to a type cast when a message is invoked on a dynamic instance. Obviously something else is going on.
The attached NUnit test case shows my problem: Using a dynamic type I can use a method only available in the concrete subclass, but I cannot do the same using a cast (results in InvalidCastException). I'd rather do the casting since this gives me full code completion in VS.
Can anyone explain what's happening and/or give me a hint how I could get code completion in my case without having to reimplement the WorkWithAndCreate-method in every concrete subclass?
cheers, Johannes
using System;
using NUnit.Framework;
namespace SlidesCode.TestDataBuilder
{
[TestFixture]
public class MyTest
{
[Test]
public void DynamicWorks()
{
string aString = CreateDynamic(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateDynamic(Action<dynamic> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
[Test]
public void CastingDoesNotWorkButThrowsInvalidCastException()
{
string aString = CreateWithCast(obj => obj.OnlyInConcreteClass());
Assert.AreEqual("a string", aString);
}
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate((Action<MyGenericClass<string>>) action);
}
}
internal abstract class MyGenericClass<T>
{
public abstract T Create();
public T WorkWithAndCreate(Action<MyGenericClass<T>> action)
{
action(this);
return this.Create();
}
}
internal class MyConcreteClass : MyGenericClass<string>
{
public override string Create()
{
return "a string";
}
public void OnlyInConcreteClass()
{
}
}
}
Here's the formatted real world example from my comment:
Customer customer = ACustomer(cust =>
{
cust.With(new Id(54321));
cust.With(AnAddress(addr => addr.WithZipCode(22222)));
});
private static Address AnAddress(Action<AddressBuilder> buildingAction)
{
return new AddressBuilder().BuildFrom(buildingAction);
}
private static Customer ACustomer(Action<CustomerBuilder> buildingAction)
{
return new CustomerBuilder().BuildFrom(buildingAction);
}
Some details are missing from it but I hope it makes the purpose clear.
The reason dynamic works is that dynamic does not depend on compile time knowledge of the object types. MyGenericClass<string> does not have the method OnlyInConcreteClass(), but the instance you are passing of course does have the method and dynamic finds this.
By the way, you can make WorkWithAndCreate work like this:
public T WorkWithAndCreate<T1>(Action<T1> action)
where T1 : MyGenericClass<T>
{
action((T1)this);
return this.Create();
}
Then, the call will work too:
private static string CreateWithCast(Action<MyConcreteClass> action)
{
return new MyConcreteClass().WorkWithAndCreate(action);
}
You now don't have to cast it anymore.
And concerning your builder, would the following work?
private static TResult AnInstance<TBuilder, TResult>(Action<TBuilder> buildingAction)
where TBuilder : Builder<TResult>, new()
{
return new TBuilder().BuildFrom(buildingAction);
}
This is an example of how to use dynamic:
http://msdn.microsoft.com/en-us/library/dd264736.aspx
You said:
My guess until now was that a dynamic type just "switches off" type checking during compilation and does something similar to a type cast when a message is invoked on a dynamic instance
Actually, it uses reflections to look up the methods, properties, and fields you invoke by name, at runtime. No casting is done, unless you actually cast the object back to its underlying type.
As for your actual problem, can you give a more concrete example? There may be a better design, but you haven't told us what you're trying to do - just what you're currently doing.
Hazarding a guess, you may want to use a base interface, and make all your functions accept that base interface. Then put the methods you want to call on that interface, and implement them in your concrete types. Usually dynamic is used as a work around when you don't have a base type, or can't modify the base type to add virtual or abstract methods.
If you really want to get this working, as-is, you must write it with a generic type parameter, not a dynamic type parameter. See Pieter's solution for how to do this properly.
I have an abstract Catalog class as follows. It has a static method OpenCatalog() which is used to return a specific concrete catalog based on the type of location provided. Once it has determined the type of catalog it then calls a specific OpenCatalog() method of the correct concrete catalog type. For example I may have an implementation of Catalog that is stored in a SQL database, or another which is stored in a file system. See the code below.
public abstract class Catalog
{
public static ICatalog OpenCatalog(string location, bool openReadOnly)
{
if(location is filePath)
{
return FileSystemCatalog.OpenCatalog(string location, bool openReadOnly);
}
else if(location is SQL server)
{
return SqlCatalog.OpenCatalog(string location, bool openReadOnly);
}
else
{
throw new ArgumentException("Unknown catalog type","location");
}
}
...
}
public abstract class FileSystemCatalog:Catalog
{
public static new ICatalog OpenCatalog(string location, bool openReadOnly)
{
//Deserializes and returns a catalog from the file system at the specified location
}
...
}
public abstract class SqlCatalog:Catalog
{
public static new ICatalog OpenCatalog(string location, bool openReadOnly)
{
//creates an returns an instances of a SqlCatalog linked to a database
//at the provided location
}
...
}
First in general is it ok to hide a static method? I know it's possible to do, but it also just seems like something that one shouldn't do very often. Also is this a valid example where it's ok to hide a static method, or is there a better way to do what I'm trying to do?
It looks like you are trying to create an abstract factory in a very awkward manner. What actually happens is you are violationg Single Responsibility Principle and mixing the catalog creation concern with the catalog concern. What you need to do is to make CatalogFactory non-static class. This gives you the flexibility to whatever you please later on (eg Dependency Injection).
public class CatalogFactory {
public ICatalog CreateCatalog(string location, bool openReadOnly)
{
if(location is filePath)
{
return OpenFileCatalog(string location, bool openReadOnly);
}
else if(location is SQL server)
{
return OpenSqlCatalog(string location, bool openReadOnly);
}
else
{
throw new ArgumentException("Unknown catalog type","location");
}
}
FileSystemCatalog OpenFileCatalog(string location, bool openReadOnly) {
return new FileSystemCatalog{/*init*/};
}
SqlCatalog OpenSqlCatalog(string location, bool openReadOnly) {
return new SqlCatalog{/*init*/};
}
}
You aren't really hiding it because you can always do
Catalog.OpenCatalog(...);
If you want the base class version. In fact, static methods are associated with a specific class and aren't virtual. It's just a nice convenience that you can call static methods defined in a base class on the derived class.
I have never found an argument against the use of private/internal static methods in terms of "code smell".
A good practical example might be an extension method inside some sort of service/utility library that you want to only extend within that library.
internal static ShippingRateType ToShippingRateType(this ProviderShippingRateType rateType) { }
Let's say we have the following piece of code:
public class Event { }
public class SportEvent1 : Event { }
public class SportEvent2 : Event { }
public class MedicalEvent1 : Event { }
public class MedicalEvent2 : Event { }
public interface IEventFactory
{
bool AcceptsInputString(string inputString);
Event CreateEvent(string inputString);
}
public class EventFactory
{
private List<IEventFactory> factories = new List<IEventFactory>();
public void AddFactory(IEventFactory factory)
{
factories.Add(factory);
}
//I don't see a point in defining a RemoveFactory() so I won't.
public Event CreateEvent(string inputString)
{
try
{
//iterate through all factories. If one and only one of them accepts
//the string, generate the event. Otherwise, throw an exception.
return factories.Single(factory => factory.AcceptsInputString(inputString)).CreateEvent(inputString);
}
catch (InvalidOperationException e)
{
throw new InvalidOperationException("Either there was no valid factory avaliable or there was more than one for the specified kind of Event.", e);
}
}
}
public class SportEvent1Factory : IEventFactory
{
public bool AcceptsInputString(string inputString)
{
return inputString.StartsWith("SportEvent1");
}
public Event CreateEvent(string inputString)
{
return new SportEvent1();
}
}
public class MedicalEvent1Factory : IEventFactory
{
public bool AcceptsInputString(string inputString)
{
return inputString.StartsWith("MedicalEvent1");
}
public Event CreateEvent(string inputString)
{
return new MedicalEvent1();
}
}
And here is the code that runs it:
static void Main(string[] args)
{
EventFactory medicalEventFactory = new EventFactory();
medicalEventFactory.AddFactory(new MedicalEvent1Factory());
medicalEventFactory.AddFactory(new MedicalEvent2Factory());
EventFactory sportsEventFactory = new EventFactory();
sportsEventFactory.AddFactory(new SportEvent1Factory());
sportsEventFactory.AddFactory(new SportEvent2Factory());
}
I have a couple of questions:
Instead of having to add factories
here in the main method of my
application, should I try to
redesign my EventFactory class so it
is an abstract factory? It'd be
better if I had a way of not having
to manually add
EventFactories every time I want to
use them. So I could just instantiate MedicalFactory and SportsFactory. Should I make a Factory of factories? Maybe that'd be over-engineering?
As you have probably noticed, I am using a inputString string as argument to feed the factories. I have an application that lets the user create his own events but also to load/save them from text files. Later, I might want to add other kinds of files, XML, sql connections, whatever. The only way I can think of that would allow me to make this work is having an internal format (I choose a string, as it's easy to understand). How would you make this? I assume this is a recurrent situation, probably most of you know of any other more intelligent approach to this. I am then only looping in the EventFactory for all the factories in its list to check if any of them accepts the input string. If one does, then it asks it to generate the Event.
If you find there is something wrong or awkward with the method I'm using to make this happen, I'd be happy to hear about different implementations. Thanks!
PS: Although I don't show it in here, all the different kind of events have different properties, so I have to generate them with different arguments (SportEvent1 might have SportName and Duration properties, that have to be put in the inputString as argument).
I am not sure about the input string question but for the first question you can likely use "convention over configuration"; a combination of reflection, the IEventFActory type and the naming you already have in place, Name.EndsWith("EventFactory") should allow you to instantiate the factories and get them into their Lists with code.
HTH ,
Berryl