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 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
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
"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
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
"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.
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
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
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
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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...
|
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
|
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...
|
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)
| |
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...
|
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...
|
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;
|
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...
|
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...
|
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...
| |
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...
|
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...
|
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...
|
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...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
| |
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...
| |