views:

237

answers:

8

Does anyone know if it is possible to prevent calling of a public constructor from outside a range of assemblies?

What I'm doing is coming up with a class library that has XML serializable classes. These classes make no sense if constructed without setting various properties so I want to prevent that state.

I'm wondering if there is a way to prevent anyone calling my public constructor, and keep it there only for serialization?

+3  A: 

Is it required that the constructors be public, or could you make them internal?

kek444
Apparently, they claim here they don't - http://stackoverflow.com/questions/267724/why-xml-serializable-class-need-a-parameterless-constructor
kek444
A: 

If you do not explicitly call any constructor in the base class, the parameterless constructor will be called implicitly. There's no way around it, you cannot instantiate a class without a constructor being called.

joe
A: 

To achieve what you are asking, you should probably make the constructor private, and then use a getInstance method to return the object if the correct assembly calls getInstance. You can do a check inside the getInstance method if you pass the object or assembly that called the function as one of its parameters.

AlbertoPL
A: 

You can create a factory method that takes assembly information in parameters and based on it you can filter it

Edit Sorry but i was making the edit and afterwards saw albertoPL answering the same

Umair Ahmed
+1  A: 

Typically, I would create a public constructor with parameters that will make the object valid and create a public parameterless constructor with valid default values.

public foo() {
  this.bar = -1;
}

public foo(int bar) {
  this.bar = bar;
}

Private/internal constructor can be used depending on your situation, and you can create a Factory pattern that deals with object creation for external code.

Adrian Godong
+1 just because I agree that normally you should initalize sensible values, however in this situation the values are other classes, which need to be correct.
Ian
+4  A: 

Check this answer: http://stackoverflow.com/questions/267724/why-xml-serializable-class-need-a-parameterless-constructor.

You may create internal or private constructor and still use XML serialization.

empi
I did not know that. I've always thought it had to be public, but I just tried it with an internal one, and it worked.
John Saunders
John. I'd be interested to know how you got that to work? All of my unit tests fail if I attempt to use anything but Public constructors.
Ian
I also tried it with private and it works. Could you post the exception?
empi
System.MissingMethodException: No parameterless constructor defined for this object..
Ian
I just added a constructor, then tried it. I just realized I didn't try to deserialize. Hold five.
John Saunders
hmm, this may be a slightly different error though, because I use element = (T)Activator.CreateInstance(elementType) as part of my custom serialization...
Ian
try (T)Activator.CreateInstance(elementType, true)
empi
In XML Serialization? Odd. At any rate, deserialization works fine with the internal parameterless constructor.
John Saunders
ah. Thanks empi. Answered both my original, and the question I never asked but needed to know. :)
Ian
A: 

I don't know if it would work in your case, but you could check the calling assembly:

if (Assembly.GetCallingAssembly().GetName().Name == "Forbidden.Assembly")
{
    throw new Exception(...);
}
Philippe Leybaert
A: 

If your actual aim is to make it impossible to instantiate an object of your class except by calling certain constructors, unfortunately that's impossible to ensure.

Daniel Earwicker
No. He thought (and so did I) that a public constructor was necessary for the XML Serializer to use, but he didn't really want a public constructor. Answer: you don't need one.
John Saunders