Factory pattern in C#: How to ensure an object instance can only be created by a factory class?
Looks like you just want to run some business logic before creating the object - so why dont you just create a static method inside the "BusinessClass" that does all the dirty "myProperty" checking work, and make the constructor private?
public BusinessClass
{
public string MyProperty { get; private set; }
private BusinessClass()
{
}
private BusinessClass(string myProperty)
{
MyProperty = myProperty;
}
public static BusinessClass CreateObject(string myProperty)
{
// Perform some check on myProperty
if (/* all ok */)
return new BusinessClass(myProperty);
return null;
}
}
Calling it would be pretty straightforward:
BusinessClass objBusiness = BusinessClass.CreateObject(someProperty);
make sure object only created by factory (C#)
If, for some reason, you need the factory and the constructed class to be in separate assemblies (which means simply using internal
won't work), and you can ensure that your factory gets a chance to run first, you can do this:
// In factory assembly:
public class Factory
{
public Factory()
{
token = new object();
MyClass.StoreCreateToken(token);
}
public MyClass Create()
{
return new MyClass(token);
}
private object token;
}
// In other assembly:
public class MyClass
{
public static void StoreCreateToken(object token)
{
if (token != null) throw new InvalidOperationException(
"Only one factory can create MyClass.");
this.token = token;
}
public MyClass(object token)
{
if (this.token != token) throw new InvalidOperationException(
"Need an appropriate token to create MyClass.");
}
private static object token;
}
Yes, it's cumbersome and awkward. But there may be weird situations where this is actually a good solution.
Benefits of a Factory for model instantiation without need for creation logic
Two benefits, one somewhat abstract and one practical.
Object instantiation is a separate responsibility. Under SRP, your business logic code should not be doing it. The responsibility of object creation belongs to the composition root and to factories.
If your code uses
new
there is more or less no way to substitute another class for unit testing. If your code uses anIXXXFactory
of some kind, your unit test code can supply its own factory which would return mock or stub objects, allowing you to isolate the class under test. This makes unit testing much easier.
Forcing the use of a factory object to instantiate a class
Some options:
- reflection
- register delegate that creates the class with factory class
- configure your DI container to behave the way you need for that type of classes
Approximate code for delegate approach:
public class Factory {
private static Dictionary<Type, Func<Model>> creators;
public void AddCreator<T>(Func<T> creator) where T:Model
{
creators.Add(typeof(T), ()=> creator());
}
public static T Instance() where T : Model
{
return (T)(creators[typeof(T)] ());
}
}
Relationship between factory design pattern and polymorphism
You use the factory pattern if you want to be able to change the concrete type that is created later on - in other words to use polymorphism to return an instance of a derived class in the form of the base class.
So polymorphism is a precondition for the factory pattern to work. Without polymorphism, you couldn't return an instance of a derived class in the form of the base class.
Related Topics
Read Big Txt File, Out of Memory Exception
Find Image Format Using Bitmap Object in C#
Execute Multiple Queries in Single Oracle Command in C#
What Is the Default Value for Enum Variable
In What Areas Might the Use of F# Be More Appropriate Than C#
Can Unity Be Made to Not Throw Synchronizationlockexception All the Time
Index of Currently Selected Row in Datagridview
Detecting Client Death in Wcf Duplex Contracts
What Is the Meaning of "This" in C#
How to Count the Number of Elements That Match a Condition with Linq
Order of Execution with Multiple Filters in Web API
Wpf Webbrowser Mouse Events Not Working as Expected
How to Interact with Windows Media Player in C#
Best Practice for Exception Handling in a Windows Forms Application