Make sure the object is created only by factory (C #)

How can I make sure that a specific class is created only by the factory, and not by directly calling new ?

EDIT: I need a factory for a separate class (for dependency injection purposes), so I cannot make it a static method of the class that will be created, and therefore I can 'make the new one private.

+6
new-operator c # factory
Sep 08 '10 at 19:45
source share
8 answers

If for some reason you need a factory and the built class in separate assemblies (which means that just using internal will not work), and you can make sure that your factory gets a chance to start, you can do this first:

 // 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 is cumbersome and uncomfortable. But there may be strange situations when this is a really good solution.

+5
08 Sep 2018-10-10T00:
source share

If the factory is in the same assembly, and you only need protection from external assemblies creating an instance of the class, you can make the constructor internal. The only way to prevent this for all other classes (including in the same assembly) is to make the class instance nested with the factory private class and only expose it as an interface. If the class is its own factory (static factory method), you can make it a private constructor, as others have mentioned.

+22
Sep 08 '10 at 19:48
source share

Make your constructors private and provide the factory method as a static method for the class itself.

In most cases, you can just make the constructors internal, letting you break the factory down into your own class - I found that often you should not try to prevent my own team from using new to create instances inside the class assembly.

+11
Sep 08 '10 at 19:46
source share

Make the constructor internal and place the factory in the same assembly.

 public MyClass { internal MyClass() { } } 

in the same assembly

 public MyClassGenerator { public static CreateMyClass() { return new MyClass(); } } 

If the factory cannot be in the same assembly or this method does not work for you, see Dan's answer

+5
Sep 08 '10 at 19:46
source share

You can make your concrete classes nested by private classes using publicly accessible constructors inside your factory class โ€” this way your factory can create them, others won't even be able to see them. In any case, you are returning from the factory of some interface / abstract class, and not a specific type. Of course, you cannot use your return type in a specific type somewhere in the client code, but at first it is a sign of poor design, and secondly, you can always get around it with a more specific interface / abstract class that inherits your nested private class.

you can refer to Eric Lippert's answer here (for a similar problem): Why would I ever need to use nested C # classes

+2
Jun 12 '17 at 15:22
source share

It will always be created by calling a new one somewhere, but if you want this to happen in your factory class, you can set all the constructors to Internal (or Private) and use the Public Static factory method of the same class).

+1
Sep 08 '10 at 19:48
source share

Many have mentioned the use of internal ones, but you can also protect your constructors and get a class that has only a static factory method. This does not stop others from doing the same, but it does a pretty good job of restricting direct access to your constructors.

+1
Sep 08 '10 at 19:57
source share

I do not like to have a factory of the type itself, especially if it is a domain object. Have an internal one if you have a separate class like factory (which I think you need). Use the InternalVisible attribute if the factory is on a different assembly.

0
Sep 08 '10 at 19:54
source share



All Articles