I have factory that looks something like the following snippet. Foo is a wrapper class for Bar and in most cases (but not all), there is a 1:1 mapping. As a rule, Bar cannot know anything about Foo, yet Foo takes an instance of Bar. Is there a better/cleaner approach to doing this?
public Foo Make( Bar obj )
{
if( obj is Bar1 )
return new Foo1( obj as Bar1 );
if( obj is Bar2 )
return new Foo2( obj as Bar2 );
if( obj is Bar3 )
return new Foo3( obj as Bar3 );
if( obj is Bar4 )
return new Foo3( obj as Bar4 ); // same wrapper as Bar3
throw new ArgumentException();
}
At first glance, this question might look like a duplicate (maybe it is), but I haven't seen one exactly like it. Here is one that is close, but not quite:
Factory based on Typeof or is a
If these are reference types, then calling as after is is an unnecessary expense. The usual idiom is to cast with as and check for null.
Taking a step back from micro-optimization, it looks like you could use some of the techniques in the article you linked to. In specific, you could create a dictionary keyed on the type, with the value being a delegate that constructs an instance. The delegate would take a (child of) Bar and return a (child of) Foo. Ideally, each child of Foo would register itself to the dictionary, which could be static within Foo itself.
Here's some sample code:
// Foo creator delegate.
public delegate Foo CreateFoo(Bar bar);
// Lookup of creators, for each type of Bar.
public static Dictionary<Type, CreateFoo> Factory = new Dictionary<Type, CreateFoo>();
// Registration.
Factory.Add(typeof(Bar1), (b => new Foo1(b)));
// Factory method.
static Foo Create(Bar bar)
{
CreateFoo cf;
if (!Factory.TryGetValue(bar.GetType(), out cf))
return null;
return cf(bar);
}
I'm not sure what you actually want to achieve. I would probably try to make it more generic.
You could use attributes on Foo, which Bar it supports, then you create a list in a initializing phase. We are doing quite a lot of stuff like this, it make adding and connecting new classes very easy.
private Dictionary<Type, Type> fooOfBar = new Dictionary<Type, Type>();
public initialize()
{
// you could scan all types in the assembly of a certain base class
// (fooType) and read the attribute
fooOfBar.Add(attribute.BarType, fooType);
}
public Foo Make( Bar obj )
{
return (Foo)Activator.CreateInstance(fooOfBar(obj.GetType()), obj);
}
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