Factory pattern in C#: How to ensure an object instance can only be created by a factory class?

C#Design PatternsOopFactory

C# Problem Overview


Recently I've been thinking about securing some of my code. I'm curious how one could make sure an object can never be created directly, but only via some method of a factory class. Let us say I have some "business object" class and I want to make sure any instance of this class will have a valid internal state. In order to achieve this I will need to perform some check before creating an object, probably in its constructor. This is all okay until I decide I want to make this check be a part of the business logic. So, how can I arrange for a business object to be creatable only through some method in my business logic class but never directly? The first natural desire to use a good old "friend" keyword of C++ will fall short with C#. So we need other options...

Let's try some example:

public MyBusinessObjectClass
{
    public string MyProperty { get; private set; }

    public MyBusinessObjectClass (string myProperty)
    {
        MyProperty = myProperty;
    }
}

public MyBusinessLogicClass
{
    public MyBusinessObjectClass CreateBusinessObject (string myProperty)
    {
        // Perform some check on myProperty

        if (true /* check is okay */)
            return new MyBusinessObjectClass (myProperty);

        return null;
    }
}

It's all okay until you remember you can still create MyBusinessObjectClass instance directly, without checking the input. I would like to exclude that technical possibility altogether.

So, what does the community think about this?

C# Solutions


Solution 1 - C#

You can make the constructor private, and the factory a nested type:

public class BusinessObject
{
    private BusinessObject(string property)
    {
    }

    public class Factory
    {
        public static BusinessObject CreateBusinessObject(string property)
        {
            return new BusinessObject(property);
        }
    }
}

This works because nested types have access to the private members of their enclosing types. I know it's a bit restrictive, but hopefully it'll help...

Solution 2 - C#

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);

Solution 3 - C#

Or, if you want to go really fancy, invert control: Have the class return the factory, and instrument the factory with a delegate that can create the class.

public class BusinessObject
{
  public static BusinessObjectFactory GetFactory()
  {
    return new BusinessObjectFactory (p => new BusinessObject (p));
  }

  private BusinessObject(string property)
  {
  }
}

public class BusinessObjectFactory
{
  private Func<string, BusinessObject> _ctorCaller;

  public BusinessObjectFactory (Func<string, BusinessObject> ctorCaller)
  {
    _ctorCaller = ctorCaller;
  }

  public BusinessObject CreateBusinessObject(string myProperty)
  {
    if (...)
      return _ctorCaller (myProperty);
    else
      return null;
  }
}

:)

Solution 4 - C#

You could make the constructor on your MyBusinessObjectClass class internal, and move it and the factory into their own assembly. Now only the factory should be able to construct an instance of the class.

Solution 5 - C#

Apart from what Jon suggested, you could also either have the factory method (including the check) be a static method of BusinessObject in the first place. Then, have the constructor private, and everyone else will be forced to use the static method.

public class BusinessObject
{
  public static Create (string myProperty)
  {
    if (...)
      return new BusinessObject (myProperty);
    else
      return null;
  }
}

But the real question is - why do you have this requirement? Is it acceptable to move the factory or the factory method into the class?

Solution 6 - C#

After so many years this got asked, and all the answers I see are unfortunately telling you how you should do your code instead of giving a straight answer. The actual answer you were looking for is having your classes with a private constructor but a public instantiator, meaning that you can only create new instances from other existing instances... that are only available in the factory:

The interface for your classes:

public interface FactoryObject
{
    FactoryObject Instantiate();
}

Your class:

public class YourClass : FactoryObject
{
    static YourClass()
    {
        Factory.RegisterType(new YourClass());
    }

    private YourClass() {}

    FactoryObject FactoryObject.Instantiate()
    {
        return new YourClass();
    }
}

And, finally, the factory:

public static class Factory
{
    private static List<FactoryObject> knownObjects = new List<FactoryObject>();

    public static void RegisterType(FactoryObject obj)
    {
        knownObjects.Add(obj);
    }

    public static T Instantiate<T>() where T : FactoryObject
    {
        var knownObject = knownObjects.Where(x => x.GetType() == typeof(T));
        return (T)knownObject.Instantiate();
    }
}

Then you can easily modify this code if you need extra parameters for the instantiation or to preprocess the instances you create. And this code will allow you to force the instantiation through the factory as the class constructor is private.

Solution 7 - C#

Yet another (lightweight) option is to make a static factory method in the BusinessObject class and keep the constructor private.

public class BusinessObject
{
	public static BusinessObject NewBusinessObject(string property)
	{
		return new BusinessObject();
	}

	private BusinessObject()
	{
	}
}

Solution 8 - C#

So, it looks like what I want cannot be done in a "pure" way. It's always some kind of "call back" to the logic class.

Maybe I could do it in a simple way, just make a contructor method in the object class first call the logic class to check the input?

public MyBusinessObjectClass
{
    public string MyProperty { get; private set; }

    private MyBusinessObjectClass (string myProperty)
    {
        MyProperty  = myProperty;
    }

    pubilc static MyBusinessObjectClass CreateInstance (string myProperty)
    {
        if (MyBusinessLogicClass.ValidateBusinessObject (myProperty)) return new MyBusinessObjectClass (myProperty);

        return null;
    }
}

public MyBusinessLogicClass
{
    public static bool ValidateBusinessObject (string myProperty)
    {
        // Perform some check on myProperty

        return CheckResult;
    }
}

This way, the business object is not creatable directly and the public check method in business logic will do no harm either.

Solution 9 - C#

In a case of good separation between interfaces and implementations the
protected-constructor-public-initializer pattern allows a very neat solution.

Given a business object:

public interface IBusinessObject { }

class BusinessObject : IBusinessObject
{
    public static IBusinessObject New() 
    {
        return new BusinessObject();
    }

    protected BusinessObject() 
    { ... }
}

and a business factory:

public interface IBusinessFactory { }

class BusinessFactory : IBusinessFactory
{
    public static IBusinessFactory New() 
    {
        return new BusinessFactory();
    }

    protected BusinessFactory() 
    { ... }
}

the following change to BusinessObject.New() initializer gives the solution:

class BusinessObject : IBusinessObject
{
    public static IBusinessObject New(BusinessFactory factory) 
    { ... }

    ...
}

Here a reference to concrete business factory is needed to call the BusinessObject.New() initializer. But the only one who has the required reference is business factory itself.

We got what we wanted: the only one who can create BusinessObject is BusinessFactory.

Solution 10 - C#

    public class HandlerFactory: Handler
    {
        public IHandler GetHandler()
        {
            return base.CreateMe();
        }
    }

    public interface IHandler
    {
        void DoWork();
    }

    public class Handler : IHandler
    {
        public void DoWork()
        {
            Console.WriteLine("hander doing work");
        }

        protected IHandler CreateMe()
        {
            return new Handler();
        }

        protected Handler(){}
    }

    public static void Main(string[] args)
    {
        // Handler handler = new Handler();         - this will error out!
        var factory = new HandlerFactory();
        var handler = factory.GetHandler();
        
        handler.DoWork();           // this works!
    }

Solution 11 - C#

I'd put the factory in the same assembly as the domain class, and mark the domain class's constructor internal. This way any class in your domain may be able to create an instance, but you trust yourself not to, right? Anyone writing code outside of the domain layer will have to use your factory.

public class Person
{
  internal Person()
  {
  }
}

public class PersonFactory
{
  public Person Create()
  {
    return new Person();
  }  
}

However, I must question your approach :-)

I think that if you want your Person class to be valid upon creation you must put the code in the constructor.

public class Person
{
  public Person(string firstName, string lastName)
  {
    FirstName = firstName;
    LastName = lastName;
    Validate();
  }
}

Solution 12 - C#

This solution is based off munificents idea of using a token in the constructor. Done in this answer make sure object only created by factory (C#)

  public class BusinessObject
    {
        public BusinessObject(object instantiator)
        {
            if (instantiator.GetType() != typeof(Factory))
                throw new ArgumentException("Instantiator class must be Factory");
        }

    }

    public class Factory
    {
        public BusinessObject CreateBusinessObject()
        {
            return new BusinessObject(this);
        }
    }

Solution 13 - C#

Multiple approaches with different tradeoffs have been mentioned.

  • Nesting the factory class in the privately constructed class only allows the factory to construct 1 class. At that point you're better off with a Create method and a private ctor.
  • Using inheritance and a protected ctor has the same issue.

I'd like to propose the factory as a partial class that contains private nested classes with public constructors. You're 100% hiding the object your factory is constructing and only exposing what you choose to through one or multiple interfaces.

The use case I heard for this would be when you want to track 100% of instances in the factory. This design guarantees no one but the factory has access to creating instances of "chemicals" defined in the "factory" and it removes the need for a separate assembly to achieve that.

== ChemicalFactory.cs ==
partial class ChemicalFactory {
    private  ChemicalFactory() {}

    public interface IChemical {
        int AtomicNumber { get; }
    }

    public static IChemical CreateOxygen() {
        return new Oxygen();
    }
}


== Oxygen.cs ==
partial class ChemicalFactory {
    private class Oxygen : IChemical {
        public Oxygen() {
            AtomicNumber = 8;
        }
        public int AtomicNumber { get; }
    }
}



== Program.cs ==
class Program {
    static void Main(string[] args) {
        var ox = ChemicalFactory.CreateOxygen();
        Console.WriteLine(ox.AtomicNumber);
    }
}

Solution 14 - C#

I don't understand why you want to separate the "business logic" from the "business object". This sounds like a distortion of object orientation, and you'll end up tying yourself in knots by taking that approach.

Solution 15 - C#

I don't think there is a solution that's not worse than the problem , all he above require a public static factory which IMHO is a worse problem and wont stop people just calling the factory to use your object - it doesnt hide anything . Best to expose an interface and/or keep the constructor as internal if you can that's the best protection since the assembly is trusted code.

One option is to have a static constructor which registers a factory somewhere with something like an IOC container.

Solution 16 - C#

Here is another solution in the vein of "just because you can doesn't mean you should" ...

It does meet the requirements of keeping the business object constructor private and putting the factory logic in another class. After that it gets a bit sketchy.

The factory class has a static method for creating business objects. It derives from the business object class in order to access a static protected construction method that invokes the private constructor.

The factory is abstract so you can't actually create an instance of it (because it would also be a business object, so that would be weird), and it has a private constructor so client code can't derive from it.

What's not prevented is client code also deriving from the business object class and calling the protected (but unvalidated) static construction method. Or worse, calling the protected default constructor we had to add to get the factory class to compile in the first place. (Which incidentally is likely to be a problem with any pattern that separates the factory class from the business object class.)

I'm not trying to suggest anyone in their right mind should do something like this, but it was an interesting exercise. FWIW, my preferred solution would be to use an internal constructor and the assembly boundary as the guard.

using System;

public class MyBusinessObjectClass
{
    public string MyProperty { get; private set; }

    private MyBusinessObjectClass(string myProperty)
    {
        MyProperty = myProperty;
    }

    // Need accesible default constructor, or else MyBusinessObjectFactory declaration will generate:
    // error CS0122: 'MyBusinessObjectClass.MyBusinessObjectClass(string)' is inaccessible due to its protection level
    protected MyBusinessObjectClass()
    {
    }

    protected static MyBusinessObjectClass Construct(string myProperty)
    {
        return new MyBusinessObjectClass(myProperty);
    }
}

public abstract class MyBusinessObjectFactory : MyBusinessObjectClass
{
    public static MyBusinessObjectClass CreateBusinessObject(string myProperty)
    {
        // Perform some check on myProperty

        if (true /* check is okay */)
            return Construct(myProperty);

        return null;
    }

    private MyBusinessObjectFactory()
    {
    }
}

Solution 17 - C#

Would appreciate hearing some thoughts on this solution. The only one able to create 'MyClassPrivilegeKey' is the factory. and 'MyClass' requires it in the constructor. Thus avoiding reflection on private contractors / "registration" to the factory.

public static class Runnable
{
    public static void Run()
    {
        MyClass myClass = MyClassPrivilegeKey.MyClassFactory.GetInstance();
    }
}

public abstract class MyClass
{
    public MyClass(MyClassPrivilegeKey key) { }
}

public class MyClassA : MyClass
{
    public MyClassA(MyClassPrivilegeKey key) : base(key) { }
}

public class MyClassB : MyClass
{
    public MyClassB(MyClassPrivilegeKey key) : base(key) { }
}


public class MyClassPrivilegeKey
{
    private MyClassPrivilegeKey()
    {
    }

    public static class MyClassFactory
    {
        private static MyClassPrivilegeKey key = new MyClassPrivilegeKey();

        public static MyClass GetInstance()
        {
            if (/* some things == */true)
            {
                return new MyClassA(key);
            }
            else
            {
                return new MyClassB(key);
            }
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionUserView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#Ricardo NoldeView Answer on Stackoverflow
Solution 3 - C#Fabian SchmiedView Answer on Stackoverflow
Solution 4 - C#Matt HamiltonView Answer on Stackoverflow
Solution 5 - C#Fabian SchmiedView Answer on Stackoverflow
Solution 6 - C#Alberto AlonsoView Answer on Stackoverflow
Solution 7 - C#Dan C.View Answer on Stackoverflow
Solution 8 - C#UserView Answer on Stackoverflow
Solution 9 - C#Reuven BassView Answer on Stackoverflow
Solution 10 - C#linView Answer on Stackoverflow
Solution 11 - C#Peter MorrisView Answer on Stackoverflow
Solution 12 - C#LindhardView Answer on Stackoverflow
Solution 13 - C#ubershmekelView Answer on Stackoverflow
Solution 14 - C#Jim ArnoldView Answer on Stackoverflow
Solution 15 - C#user1496062View Answer on Stackoverflow
Solution 16 - C#yoyoView Answer on Stackoverflow
Solution 17 - C#Ronen GlantsView Answer on Stackoverflow