473,544 Members | 1,944 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Making constructor visible only to a certain class

This is a design question.

I have a project containing a dozen or so classes with protected
internal constructors.

My reason for having protected internal constructors is to prevent
classes in other assemblies from instantiating them. There is a factory
class that instantiates them. Only the factory should do so, because
some of these classes have subclasses that will be created instead. The
decision of which class to instantiate belongs to the factory.

I've got this working just fine, except one detail.

Because the constructors are protected internal, it's possible for
classes inside the project to by-pass the factory. It's not too hard to
ensure this doesn't happen, by checking manually within the project;
but it would be easier and safer if the compiler could catch this
mistake.

Ideally, I'd like the constructors to have a more restricted visibility
than "internal". I'd like to specify that only the factory can see
them. I.e., instead of this:

protected internal Foo() {}

I'd like to be be able to write:

protected visibleto(Facto ry) Foo() {}

Unfortunately, C# has extremely coarse-grained visiblity modifiers.

I can think of a couple of work-arounds:

Work-around 1. Declare the constructors protected and let the factory
use reflection to instantiate them.

Work-around 2. Declare a nested protected class within the factory for
each of the classes it instantiates. The nested classes would have
public constructors. Then only the factory, or its descendants, could
instantiate the classes. Exactly what I want!

Both solutions would be worse than the original problem. Reflection
(Work-around 1) kills type-safety, so I avoid it unless I absolutely
need it; besides, it's slow. Work-around 2, on the other hand, would be
a bad case of code-bloat.

Is there a decent solution to this in C#?

-- Peter Gummer
Feb 20 '06 #1
18 6490
It would be nice if there was a "friend" concept in c#. If I may ask, why
can you not trust the code within your own assembly?

"Peter Gummer" <pe************ ******@hotnospa mmail.com> wrote in message
news:ec******** ******@TK2MSFTN GP09.phx.gbl...
This is a design question.

I have a project containing a dozen or so classes with protected
internal constructors.

My reason for having protected internal constructors is to prevent
classes in other assemblies from instantiating them. There is a factory
class that instantiates them. Only the factory should do so, because
some of these classes have subclasses that will be created instead. The
decision of which class to instantiate belongs to the factory.

I've got this working just fine, except one detail.

Because the constructors are protected internal, it's possible for
classes inside the project to by-pass the factory. It's not too hard to
ensure this doesn't happen, by checking manually within the project;
but it would be easier and safer if the compiler could catch this
mistake.

Ideally, I'd like the constructors to have a more restricted visibility
than "internal". I'd like to specify that only the factory can see
them. I.e., instead of this:

protected internal Foo() {}

I'd like to be be able to write:

protected visibleto(Facto ry) Foo() {}

Unfortunately, C# has extremely coarse-grained visiblity modifiers.

I can think of a couple of work-arounds:

Work-around 1. Declare the constructors protected and let the factory
use reflection to instantiate them.

Work-around 2. Declare a nested protected class within the factory for
each of the classes it instantiates. The nested classes would have
public constructors. Then only the factory, or its descendants, could
instantiate the classes. Exactly what I want!

Both solutions would be worse than the original problem. Reflection
(Work-around 1) kills type-safety, so I avoid it unless I absolutely
need it; besides, it's slow. Work-around 2, on the other hand, would be
a bad case of code-bloat.

Is there a decent solution to this in C#?

-- Peter Gummer

Feb 20 '06 #2
Peter Rilling wrote:
It would be nice if there was a "friend" concept in c#. If I may
ask, why can you not trust the code within your own assembly?


Well, I can trust it only insofar as I am infallible. I am but human,
so I'm sure to make mistakes :-)

It would be very easy to forget to use the factory. New developers will
also have to learn that my design involves calling the factory. I have
documented the design, but if someone fails to read the documentation
then they will probably just write "new Foo()" instead of
"Factory.NewFoo ".

My preference is for Eiffel, not C++, so I was wishing for "selective
export" rather than "friend". But you get the idea.

-- Peter Gummer
Feb 20 '06 #3
"Peter Gummer" <pe************ ******@hotnospa mmail.com> a écrit dans le
message de news: ec************* *@TK2MSFTNGP09. phx.gbl...

| Because the constructors are protected internal, it's possible for
| classes inside the project to by-pass the factory. It's not too hard to
| ensure this doesn't happen, by checking manually within the project;
| but it would be easier and safer if the compiler could catch this
| mistake.

How about using the InternalsVisibl eTo attribute to allow one assembly
access to something internal from another assembly.

This means that you could declare your classes with internal constructors in
one assembly and the factory in a "friend" assembly. As long as the factory
is the only class in the "friend" assembly, then it will be the only class
that can instantiate your types.

Joanna

--
Joanna Carter [TeamB]
Consultant Software Engineer
Feb 20 '06 #4
Joanna Carter [TeamB] wrote:
"Peter Gummer" <pe************ ******@hotnospa mmail.com> a écrit dans le
message de news: ec************* *@TK2MSFTNGP09. phx.gbl...

| Because the constructors are protected internal, it's possible for
| classes inside the project to by-pass the factory. It's not too hard to
| ensure this doesn't happen, by checking manually within the project;
| but it would be easier and safer if the compiler could catch this
| mistake.

How about using the InternalsVisibl eTo attribute to allow one assembly
access to something internal from another assembly.

This means that you could declare your classes with internal constructors in
one assembly and the factory in a "friend" assembly. As long as the factory
is the only class in the "friend" assembly, then it will be the only class
that can instantiate your types.

Joanna


That's a cool one :-). I wish I knew that a year ago.

But this applies just for the complete type, not one of its fields. I
think the OPs intend was to declare just the ctors private.

Here's a way to make the just ctor private:

public class AA
{
private AA() { }
}

public static class AAFactory
{
public static AA CreateAA()
{
return (AA)Activator.C reateInstance(t ypeof(AA), true);
}
public static T Create<T>()
{
return (T)Activator.Cr eateInstance(ty peof(T), true);
}
}

AA a1 = AAFactory.Creat e<AA>();
AA a2 = AAFactory.Creat eAA();
However, if it is possible for the factory just to return a base class
or interface, Joannas aproach is the cleanest.

HTH,
Andy
--
To email me directly, please remove the *NO*SPAM* parts below:
*NO*SPAM*xmen40 @*NO*SPAM*gmx.n et
Feb 20 '06 #5

"Peter Gummer" <pe************ ******@hotnospa mmail.com> wrote in message
news:ec******** ******@TK2MSFTN GP09.phx.gbl...
This is a design question.

I have a project containing a dozen or so classes with protected
internal constructors.

My reason for having protected internal constructors is to prevent
classes in other assemblies from instantiating them. There is a factory
class that instantiates them. Only the factory should do so, because
some of these classes have subclasses that will be created instead. The
decision of which class to instantiate belongs to the factory.


"protected internal" allows calling by the ctors of derived classes which
doesn't sound like what you want.
Feb 20 '06 #6
Why not just make the constructors private and use the factory thing
everywhere?

One more thing, have you checked FxCop? I think you can make a rule in it
and it'll do the enforcement of not using "new" that you want in your
current approach. Just an idea.

Regards.

-Ab.

"Peter Gummer" <pe************ ******@hotnospa mmail.com> wrote in message
news:ec******** ******@TK2MSFTN GP09.phx.gbl...
This is a design question.

I have a project containing a dozen or so classes with protected
internal constructors.

My reason for having protected internal constructors is to prevent
classes in other assemblies from instantiating them. There is a factory
class that instantiates them. Only the factory should do so, because
some of these classes have subclasses that will be created instead. The
decision of which class to instantiate belongs to the factory.

I've got this working just fine, except one detail.

Because the constructors are protected internal, it's possible for
classes inside the project to by-pass the factory. It's not too hard to
ensure this doesn't happen, by checking manually within the project;
but it would be easier and safer if the compiler could catch this
mistake.

Ideally, I'd like the constructors to have a more restricted visibility
than "internal". I'd like to specify that only the factory can see
them. I.e., instead of this:

protected internal Foo() {}

I'd like to be be able to write:

protected visibleto(Facto ry) Foo() {}

Unfortunately, C# has extremely coarse-grained visiblity modifiers.

I can think of a couple of work-arounds:

Work-around 1. Declare the constructors protected and let the factory
use reflection to instantiate them.

Work-around 2. Declare a nested protected class within the factory for
each of the classes it instantiates. The nested classes would have
public constructors. Then only the factory, or its descendants, could
instantiate the classes. Exactly what I want!

Both solutions would be worse than the original problem. Reflection
(Work-around 1) kills type-safety, so I avoid it unless I absolutely
need it; besides, it's slow. Work-around 2, on the other hand, would be
a bad case of code-bloat.

Is there a decent solution to this in C#?

-- Peter Gummer

Feb 20 '06 #7
Nick Hounsome wrote:
"protected internal" allows calling by the ctors of derived classes
which doesn't sound like what you want.


That's exactly what I want.

I'm not trying to restrict the capabilities of subclasses. I'm trying
to restrict the capabilities of clients; i.e., I don't want other
objects to be able to instantiate the product classes. Only the factory
should instantiate them.

So no: I definitely do not want "internal"; "protected internal" is
closer to what I want. My problem is that "internal" is too crude a
mechanism; "protected" is just fine.

-- Peter Gummer
Feb 20 '06 #8
Abubakar wrote:
Why not just make the constructors private and use the factory thing
everywhere?


If I made the constructors "private" (or "protected" ), the factory
would not have access to the constructors, so it would be unable to
instantiate the product classes -- unless, of course, I used one of the
two work-arounds that I mentioned in my original post (i.e. reflection,
for which Andreas Mueller gave sample code, or writing a protected
subclass for each product class nested within the factory) -- both of
which cures I feel are worse than the original problem.

Am I missing something in your "private" suggestion?

Thanks for the FxCop idea. We might end up doing that. It's a pain,
though, having to use a tool like FxCop to overcome the deficiencies of
the language.

-- Peter Gummer
Feb 20 '06 #9
Joanna Carter [TeamB] wrote:
How about using the InternalsVisibl eTo attribute to allow one
assembly access to something internal from another assembly.

This means that you could declare your classes with internal
constructors in one assembly and the factory in a "friend" assembly.
As long as the factory is the only class in the "friend" assembly,
then it will be the only class that can instantiate your types.


Something like that might work. I didn't know about InternalsVisibl eTo.

I wouldn't make the constructors "internal", though. That's exactly
what I'm trying to prevent: products within the assembly creating each
other directly. If I simply made the constructors "protected" , then
your idea should work.

The idea of adding another project, containing nothing but the factory,
doesn't really appeal to me. I actually have several factories (a fact
I didn't mention earlier), so I'd finish up with several teensy-weensy
factory projects. My initial feeling is that this is another cure worse
than the original problem; but I'll think about it.

Thanks for the suggestion.

-- Peter Gummer
Feb 20 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
3547
by: Martin Oddman | last post by:
Hi, I have a compiling problem. Please take a look at the code below. I have an application that is built upon three tiers: one data tier (Foo.DataManager), one business tier (Foo.Kernel) and one web presentation tier (Foo.WebFiles). The data tier shall only be accessible thru the business tier so I do NOT want a reference to the data tier...
20
4224
by: Ole Hanson | last post by:
I am accessing my database through an interface, to allow future substitution of the physical datastore - hence I would like to declare in my Interface that my DAL-objects implementing the interface and accessing the datastore MUST pass in a UserToken in the constructor of the object. Is this not possible? Am I forced to add the UserToken...
5
9125
by: Tarscher | last post by:
Hi all, I have a user control and a form. I want the user control to be visible when the form is shown. I haven't found a good webtutorial on this so maybee someone can help me out? regards Stijn
9
3169
by: tshad | last post by:
I have a datagrid that I want to add a new column to. This column will only be visible under certain conditions. So I want to set the column visible=false. Then when the right condition happens to change it to visible=true. You can't do that with a bound column (no ID), but you can create a templatecolumn with a label. To make these...
15
1880
by: Sam Kong | last post by:
Hello! I got recently intrigued with JavaScript's prototype-based object-orientation. However, I still don't understand the mechanism clearly. What's the difference between the following two? (1)
2
1776
by: libsfan01 | last post by:
hi! i have written a function to make visible elements with a certain id. however i intended it to be used to make visible multiple elements but it only appears to switch on the first element it comes to with that id. after that it appears to stop. i was wondering how i can adapt this function to make visible multiple elements, will i need...
5
2106
by: ffrugone | last post by:
My scenario involves two classes and a database. I have the classes "Broom" and "Closet". I want to use a static method from the "Closet" class to search the database for a matching "Broom". If it finds a matching "Broom", i want it to return a "Broom" object to the calling program. I want the static method to call the constructor for the...
10
2397
by: JosephLee | last post by:
In Inside C++ object Model, Lippman said there are four cases in which compile will sythesize a default constructor to initialize the member variables if the constructor is absent: 1. there is a virtual function; 2. virtual inheritance; 3.base class with explicit default constructor;
16
2369
by: Andrea Gavana | last post by:
Hi Diez & All, Do you mind explaining "why" you find it *buttugly*? I am asking just out of curiosity, obviously. I am so biased towards wxPython that I won't make any comment on this thread in particular, but I am curious to know why some people find it "ugly" or "bad" or whatever. It has its own bugs and missing features, of course, but...
0
7420
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7362
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7764
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
7704
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
5904
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5291
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
3407
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3404
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
657
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.