I have a Factory class where i instantiate classes based on string matching.
Example Snippet:
class Factory
{
Dictionary test = new Dictionary(string, ICreate);
public FactoryMethod()
{
test.Add("classA",new a());
test.Add("classB",new b());
test.Add("classC",new c());
}
public ICreate Create(string toMatch)
{
return test[toMatch];
}
}
But now i want to match few number of patterns (file paths) and then instantiate the classes based on the patterns matched.
So my question is where can i store these patterns that i want to match? Should they be in a "table" in my DB or can i have a hashtable here (which maps to a class to intantiate, when any one of the pattern matches )?
First of all, your Create
method doesn't actually create anything. It returns an instance that was already created. Every call to Create
will return the same instance.
If that's what you want, fine, but if you want a new instance each time, may I make a suggestion? Instead of storing an object, store a function that returns a new object:
class Factory
{
Dictionary<string,Func<ICreate>> test = new Dictionary<string,Func<ICreate>>();
public Factory()
{
test.Add( "classA", () => new a() );
test.Add( "classB", () => new b() );
test.Add( "classC", () => new c() );
}
public ICreate Create(string toMatch)
{
var creationFunction = test[toMatch];
return creationFunction();
}
}
See how that works? The lambda expression () => new a()
can be called like a function and will instantiate a new a
with every call.
As for pattern matching, you can do something similar. We put a function in for the value; now let's put one in for the key. Instead of storing a string, we'll store a function that accepts a string and returns a Boolean. Then all we have to do is search for the first dictionary entry where executing the key returns true.
class Factory
{
Dictionary<Func<string,bool>,Func<ICreate>> _map = new Dictionary<Func<string,bool>, Func<ICreate>>();
public Factory()
{
_map.Add
(
a => a.Contains("classA"),
() => new a()
);
_map.Add
(
a => a.Contains("classB"),
() => new b()
);
_map.Add
(
a => a.Contains("classC"),
() => new c()
);
}
public ICreate Create(string toMatch)
{
var func = _map.Where( e => e.Key(toMatch) ).First().Value;
return func();
}
}
public class Program
{
static public void Main()
{
var f = new Factory();
var o = f.Create("c:\folder\subfolder\classA");
Console.WriteLine("You just created an instance of '{0}'.", o.GetType().Name);
}
}
Output:
You just created an instance of 'a'.
In this example we did pattern matching with Contains()
, but since it is Func you can write any expression you want, using any of the string functions, regular expressions, you name it. You can also mix and match; for example, ,you could use a regular expression to identify a pattern that requires a ClassA, but you could use a regular ==
comparison to identify a pattern for ClassB. Also, we can change the LINQ function from First
to Single
if you want to ensure that whatever string was submitted matches one and only one pattern.