Selective visibility of public methods in DLL?

B

Byron

I’m trying to come up with a way to selectively expose public methods (and
possibly properties) in a class within a DLL using .NET 3.5. I suspect this
is a fairly noobie question.

I have a class that can control several different serial devices. These
devices share some common methods such Start() and Stop() and some have other
specialized methods unique to them, like Pause() and Resume(). What I want
to be able to do is require the user of the class to supply the type of
device they are controlling, and restrict the public methods – and properties
- to those that are legal for the current device. There are hundreds of
public methods in the class, but no single device uses them all, so I want to
hide those that don’t apply to the current device type.

For example, given:

Controller c = new Controller(DeviceType1);
c.Start(), c.Stop(), c.Pause(), and c.Resume() are visible

But when:
Controller c = new Controller(DeviceType2);
c.Start() and c.Stop() are visible but c.Pause() and c.Resume() are NOT
visible

Any suggestions would be greatly appreciated.
 
P

Peter Duniho

Byron said:
I’m trying to come up with a way to selectively expose public methods (and
possibly properties) in a class within a DLL using .NET 3.5. I suspect this
is a fairly noobie question.

Well, inasmuch as a I suspect someone more experienced with OOP design
wouldn't ask it, sure. :)

Based on your description:
I have a class that can control several different serial devices. These
devices share some common methods such Start() and Stop() and some have other
specialized methods unique to them, like Pause() and Resume(). What I want
to be able to do is require the user of the class to supply the type of
device they are controlling, and restrict the public methods – and properties
- to those that are legal for the current device. There are hundreds of
public methods in the class, but no single device uses them all, so I want to
hide those that don’t apply to the current device type.

Typically, the way something like this would be managed would be to have
a base class that represents the common functionality, and then
subclasses that contain the specialized functionality.
For example, given:

Controller c = new Controller(DeviceType1);
c.Start(), c.Stop(), c.Pause(), and c.Resume() are visible

But when:
Controller c = new Controller(DeviceType2);
c.Start() and c.Stop() are visible but c.Pause() and c.Resume() are NOT
visible

Any suggestions would be greatly appreciated.

You cannot do things literally as you are asking. In a given class, a
member's accessibility is immutable. If it's ever public, it's always
public. So whatever is visible in the Controller type, will always be
visible in the Controller type.

What you can do is make Controller your base class, with Start() and
Stop() in it, and then have a sub-class that inherits Controller and
which declares the Pause() and Resume() methods.

In that approach, instead of using "new Controller(DeviceType1)", you'll
either have to instantiate the specific sub-class type explicitly, or
have a factory method (e.g. a static method in the Controller class)
that given a "DeviceType1", can figure out what the actual sub-class to
instantiate is and create and return an instance of that sub-class.

As an elaboration on that technique, if there is a sensible way to group
the various members that have this "optional visibility", you can
declare specific interfaces that have those members, and then have each
Controller sub-class implement the interfaces as appropriate to that
object. That way, rather than casting to the sub-class itself, you can
essentially query a given object for what functionality it supports by
checking for interface implementation using the "as" operator. This
would work particularly well with the factory method approach, because
otherwise the factory is kind of pointless, since you'd still have to
know the exact type being returned to get at the specialized members.

Here are some code examples illustrating the above:

class Controller
{
public void Start() { /* implementation here */ }
public void Stop() { /* implementation here */ }
}

class SpecificController : Controller
{
public void Pause() { /* ... */ }
public void Resume() { /* ... */ }
}

class Client
{
void SomeMethod(int type)
{
Controller controller = null;

switch (type)
{
case TypePlain:
controller = new Controller();
break;
case TypeSpecific:
controller = new SpecificController();
break;
// etc.
}

controller.Start();

if (type == TypeSpecific)
{
SpecificController specific = (SpecificContoller)controller;

specific.Resume();
specific.Pause();
}

controller.Stop();
}
}

or, alternatively:

interface IPlainController
{
void Start();
void Stop();
}

interface IPausableController : PlainController
{
void Pause();
void Resume();
}

class Controller : IPlainController
{
public void Start() { /* implementation here */ }
public void Stop() { /* implementation here */ }

public static Controller Create(int type)
{
switch (type)
{
case TypePlain:
return new Controller();
case TypeSpecific:
return new SpecificController();
// etc.
}
}
}

class SpecificController : Controller, IPausableController
{
public void Pause() { /* ... */ }
public void Resume() { /* ... */ }
}

class Client
{
void SomeMethod(int type)
{
Controller controller = Controller.Create(type);

controller.Start();

IPausableController pausable = controller as IPausableController;

if (pausable != null)
{
controller.Resume();
controller.Pause();
}

controller.Stop();
}
}

The latter is more complex in terms of implementation, but offers more
flexibility in usage. It allows the code to avoid special-casing
specific object types, and instead control execution flow based on the
features implemented by each controller type.

Regardless of how you approach the problem, there is always going to be
some difficulty dealing with a class hierarchy in which you have a
variety of classes with disparate features, but which you are trying to
use together and at the same time. Without knowing more about your
specific design goals, it's hard to offer better advice, but in general
it's easier to deal with the class design if when a sub-class has
specific features not found in the base class that you want to take
advantage of, you can write the code so that it always knows the type of
that sub-class.

Pete
 
B

Byron

Thanks for the thorough reply.

I’ll actually only be implementing a single interface at a time, but the DLL
is intended to be used across multiple products with a different GUI for
each. The serial communication is standardized across all devices, so a
Start message is the same for all devices that implement it, but not all do.

I’m just trying to minimize the possibility of a developer sending a message
to a device that it doesn’t implement, even though it should just be ignored
by the target device. I’d rather a developer not even see a method that the
target device doesn’t implement, but we want to avoid having separate
communication DLLs for each product line.
 
P

Peter Duniho

Byron said:
Thanks for the thorough reply.

I’ll actually only be implementing a single interface at a time, but the DLL
is intended to be used across multiple products with a different GUI for
each. The serial communication is standardized across all devices, so a
Start message is the same for all devices that implement it, but not all do.

I’m just trying to minimize the possibility of a developer sending a message
to a device that it doesn’t implement, even though it should just be ignored
by the target device. I’d rather a developer not even see a method that the
target device doesn’t implement, but we want to avoid having separate
communication DLLs for each product line.

A class with hundreds of public methods in it is just asking to be
refactored into a more sensible, simple design.

That said, there is ample precedent for certain methods being
"optional". The classes would "implement" the methods simply by
throwing a NotSupportedException. You can simplify the implementor's
job by providing a base class where the optional methods are all
virtual, and the implementation in the base class is where the exception
is thrown. Then the derived classes only need to override the methods
they really do support.

Alternatively, my suggestion about using interfaces would also work.
And in fact, while you haven't shared enough about your specific
situation for anyone else to know for sure, given the very large number
of public methods in your class, it sure seems like breaking the
functionality of the class into interfaces is at least in part a good
idea (as part of refactoring the class so that it makes more sense).

Pete
 
H

Helmut Giese

Hi,
Typically, the way something like this would be managed would be to have
a base class that represents the common functionality, and then
subclasses that contain the specialized functionality. [snip]
What you can do is make Controller your base class, with Start() and
Stop() in it, and then have a sub-class that inherits Controller and
which declares the Pause() and Resume() methods.

Of course the advice to use an inheritance hierarchy is valid -
although maybe not very attractive: If the number of different devices
is significant one can suffer a combinatorial explosion of
combinations.

Which makes me wonder: Does C# support 'mixins'?
A 'mixin' (as I know it from other OO environments) is a mechanism
which allows you to add certain functionality to a class (sometimes
even to individual objects) _independent_ of the inheritance
hierarchy.

As an example: Suppose that some devices support hardware handshake,
some support support handshake (e.g. XON/XOFF) and some support none.
Instead of having classes
- DeviceWPauseAndResume
- DeviceWPauseAndResumeAndHWHandsh
- DeviceWPauseAndResumeAndXonXff
one would take a DeviceWPauseAndResume and would 'mixin' the desired
handshake method.

Just wondering if something like this exists in C#. Best regards
Helmut Giese
 
P

Peter Duniho

Helmut said:
Of course the advice to use an inheritance hierarchy is valid -
although maybe not very attractive: If the number of different devices
is significant one can suffer a combinatorial explosion of
combinations.

Indeed. IMHO, part of the problem is that the OP is dealing with a
single class that has hundreds of public methods. Surely there is a
better way to factor that functionality.
Which makes me wonder: Does C# support 'mixins'?

That depends on exactly what you mean.
A 'mixin' (as I know it from other OO environments) is a mechanism
which allows you to add certain functionality to a class (sometimes
even to individual objects) _independent_ of the inheritance
hierarchy.

C# has two approaches:

– interfaces, which require the cooperation of the class being extended
– extension methods, which do not

I've suggested that _maybe_ interfaces would help the OP design his code
so that it's more manageable and offers what he wants. Hard to say for
sure without more details about the existing design.

Given the example, I doubt that extension methods would be helpful here,
but again I can't say for sure. The only other OO environment I use
regularly that has an equivalent design is Objective-C, with its
categories, and those are not quite like extension methods in C# (which
are strictly compile-time only, and have access only to public members
of the type being extended). So I don't know whether your idea of a
"mixin' applies to C#.
As an example: Suppose that some devices support hardware handshake,
some support support handshake (e.g. XON/XOFF) and some support none.
Instead of having classes
- DeviceWPauseAndResume
- DeviceWPauseAndResumeAndHWHandsh
- DeviceWPauseAndResumeAndXonXff
one would take a DeviceWPauseAndResume and would 'mixin' the desired
handshake method.

If those methods can be implemented without access to private members of
the extended class, then that could work. Except that you lose the
ability to enforce the methods being present in only some classes, since
an extension method applies to a specific type.

On the one hand, it means there's no need to reimplement the
functionality in each and every specific object type. On the other
hand, it means that each and every specific object type winds up having
the implementation, which (based on his question about changing
visibility of the methods) may not be what the OP wants.

Pete
 
H

Helmut Giese

Hi Peter,
That depends on exactly what you mean.
ok, this risks to get wildly off topic, but anyway ...

The system I was thinking of is XOTcl - an extension to Tcl - and the
most powerful OO system I ever encountered. An example showing the
concept of mixins in a rather compact way can be found at
http://wiki.tcl.tk/10970

Now, seeing Tcl code for the first time may well be irritating so
maybe some hints are in order:
- The 1st word is always a command, what follows are its parameters.
So 'foo bar baz' would be like foo(bar, baz) in C/Java/ you name it.
- Things in brackets ([...]) are used for nested commands. They get
evaluated first and are replaced by their result.
So 'foo [bar baz]' would call 'bar baz' and then pass the result to
foo - like foo(bar(baz));
- If 'v' is a variable, '$v' retrieves its value.

For further (introductory) information I would recommend the XOTcl
tutorial at
http://media.wu-wien.ac.at/doc/index.html

Ok, enough of this OT stuff :)
Have a nice weekend
Helmut Giese
 
P

Peter Duniho

Helmut said:
Hi Peter,

ok, this risks to get wildly off topic, but anyway ...

The system I was thinking of is XOTcl - an extension to Tcl - and the
most powerful OO system I ever encountered.

I always view the use of the word "powerful" as applied to programming
languages with a large dose of skepticism. Too often, "powerful" is
confused with "complex".

When someone comes up with a precise, empirical method for measuring
"power" in a programming language, then I'll take the term seriously. :)
An example showing the
concept of mixins in a rather compact way can be found at
http://wiki.tcl.tk/10970

Hmmm…looks like a multiple inheritance free-for-all. :)

Anyway, there's nothing in C# like that. In fact, extension methods
cannot be used in exactly that way, because class methods always take
precedence of extension methods. If you had two methods with the same
name, one in the class and one as an extension method, the extension
method would be ignored.

Of course, you could use a slightly different name, but the extension
method is still very specific to the type being extended. In the
example you've provided, the "mixin" type is completely independent of
the type being extended, yet apparently able to chain to the previous
implementation of a method knowing nothing about the implementor of that
method.

To large extent, this is due to the disparity between XOTcl and C# in
their fundamental design. From the example, it appears that XOTcl is
strongly dynamic, and possibly interpreted as well. On the other hand,
C# is specifically designed for static typing, with as much resolved at
compile time as possible. It's much more like C++ or Java, than the
Smalltalk-based languages or other dynamic OOP languages.

Since things need to be resolved statically in C#, you're not going to
see that sort of dynamic extension. The only polymorphic behavior
available is when it's been designed into a class from the outset.

It's unclear from the example given what access a mixin type has to the
type being extended. But, assuming XOTcl has accessibility rules, and
assuming a mixin type does not have access except to public members of
another type, then one could in fact implement something similar, though
not identical, to mixins in XOTcl using extension methods.

Still, it's not clear to me that would benefit the OP here. Just
judging from the names of the methods, I suspect that they actually
involve some specific change of state in the objects, and in C# the
extension methods have no place to maintain that state, if it's not
already exposed as a public member of the class being extended.

Pete
 
J

J.B. Moreno

Byron said:
I’Äôm trying to come up with a way to selectively expose public methods (and
possibly properties) in a class within a DLL using .NET 3.5. I suspect this
is a fairly noobie question.

I have a class that can control several different serial devices. These -snip-
For example, given:

Controller c = new Controller(DeviceType1);
c.Start(), c.Stop(), c.Pause(), and c.Resume() are visible

But when:
Controller c = new Controller(DeviceType2);
c.Start() and c.Stop() are visible but c.Pause() and c.Resume() are NOT
visible

Any suggestions would be greatly appreciated.

Interfaces.

IDeviceType c = (IDeviceTpye) new Controller();

The device type to the constructor would be optional (but I'd recommend
it).

You can define hundreds of different interfaces for a single class if
you like.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top