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 fact
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...
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.
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;
}
}
:)
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
.
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();
}
}
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.