C# ServicedComponent Singleton

D

David

Hello,
I'm writing a C# class library that may be called by non-.Net
applications. The main class of this class libray is a ServicedComponent
so that non-.Net application can call this class as a standard COM+
component. Now, I want that class to be a singleton. Once loaded, the
values moslty never change.
I tried using this pattern:

public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();

private Singleton(){}

public static Singleton Instance
{
get
{
return instance;
}
}
}

However, it throws an exception complaining about ServicedComponent
thats needs a public constructor.
The error raised is:

An unhandled exception of type
'System.EnterpriseServices.RegistrationException' occurred in
system.enterpriseservices.dll

Additional information: Invalid ServicedComponent-derived classes were
found in the assembly.
(Classes must be public, concrete, have a public default constructor,
and meet all other ComVisibility requirements)
 
D

David Browne

David said:
Hello,
I'm writing a C# class library that may be called by non-.Net
applications. The main class of this class libray is a ServicedComponent
so that non-.Net application can call this class as a standard COM+
component. Now, I want that class to be a singleton. Once loaded, the
values moslty never change.
I tried using this pattern:

public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();

private Singleton(){}

public static Singleton Instance
{
get
{
return instance;
}
}
}

There are two different "kinds" of singletons. There's the kind of
singleton
However, it throws an exception complaining about ServicedComponent
thats needs a public constructor.
The error raised is:

An unhandled exception of type
'System.EnterpriseServices.RegistrationException' occurred in
system.enterpriseservices.dll

Additional information: Invalid ServicedComponent-derived classes were
found in the assembly.
(Classes must be public, concrete, have a public default constructor,
and meet all other ComVisibility requirements)

Right. Singletons cannot be exposed as COM components. The easiest fix for
this is to publish a facade class for your COM clients.

public sealed class SingletonFacade
{
public SingletonFacade() {}
public void Foo()
{
Singleton.instance.Foo();
}
//etc
}

David
 
W

Willy Denoyette [MVP]

Implement your component as a pooled object with a min/max of 1 objects in
the pool and enable JITA.
Don't forget to SetComplete to true when returning after a call else you
will block further calls.

Willy.
 
A

Anders Borum

Hello!
The easiest fix for this is to publish a facade class for your COM
clients.

Couldn't one argue that it's an adapter class also? (I'm talking patterns
here :)
 
D

David Browne

Anders Borum said:
Hello!

clients.

Couldn't one argue that it's an adapter class also? (I'm talking patterns
here :)

I agree that this is more of the adapter pattern. Calling it a facade class
is really J2EE-speak.

David
 
D

David

Hello,
I'm not familiar with JITA pooled objects.
Setting min/max to 1 will ensure only one single instance will always be
loaded into memory? What about variables set into the component?

Let say I have 2 methods in this component, SetValues and GetValues.
Another application that launches at startup of Windows sets the values
in the singleton passing the values to the SetValues method. This method
stores values into static variables in the singleton component and
issues a SetComplete (or the component can be set to "autocomplete").
Then many other applications can call the GetValues to get the values
previously provided to the singleton. Will this senario work?

Thanks,
David.
 
W

Willy Denoyette [MVP]

David said:
Hello,
I'm not familiar with JITA pooled objects.
Setting min/max to 1 will ensure only one single instance will always be
loaded into memory? What about variables set into the component?

Let say I have 2 methods in this component, SetValues and GetValues.
Another application that launches at startup of Windows sets the values
in the singleton passing the values to the SetValues method. This method
stores values into static variables in the singleton component and
issues a SetComplete (or the component can be set to "autocomplete").
Then many other applications can call the GetValues to get the values
previously provided to the singleton. Will this senario work?

Sure, global state is preserved between calls, per client state however is
not.
You can assign a value to your (private) statics (your global state) in the
constructor, so that they are initialized once at object creation time. Once
assigned they remain for the lifetime of the application, and you can use
propety get to retrieve your global state.

Willy.
 
D

David Browne

Willy Denoyette said:
Sure, global state is preserved between calls, per client state however is
not.
You can assign a value to your (private) statics (your global state) in
the constructor, so that they are initialized once at object creation
time. Once assigned they remain for the lifetime of the application, and
you can use propety get to retrieve your global state.

But this is not just a singleton, this is a serialized singleton. There's
no need to serialize all your clients just to get access to global state.

David
 
D

David Browne

David said:
What do you mean by serialized singleton?

If you have two different threads, or two different processes trying to
access the object, they will be serialized. One will wait until the other
has released the reference to the object. Not just the method calls will be
serialized, but whole sequence of client code using the object

obj = CreateObject(...)
obj.MethodA
obj.MethodB
set obj = null

will be strictly serialized. A second thread or process will block on
CreateObject until the previous thread has released the reference with set
obj=null.


See

From "Everyone Into the Pool" by Rockford Lhotka
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnadvnet/html/vbnet11262002.asp

In either case, if a client requests an object but we already have the
maximum number loaded and in use, the client request is blocked. When an
object does become free, the object is used to service the blocked client
request.

See also

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconobjectpooling.asp

David
 
W

Willy Denoyette [MVP]

David Browne said:
If you have two different threads, or two different processes trying to
access the object, they will be serialized. One will wait until the other
has released the reference to the object. Not just the method calls will
be serialized, but whole sequence of client code using the object

obj = CreateObject(...)
obj.MethodA
obj.MethodB
set obj = null

will be strictly serialized. A second thread or process will block on
CreateObject until the previous thread has released the reference with set
obj=null.

This is not exactly true, that's the purpose of the JITA mechanism and
ContextUtil.SetComplete (or [AutoComplete(true)]), as soon as a method ends
the object returns to the pool where it waits to be re-activated.
Any number of clients (subject to scalability) can CREATE and KEEP a
reference a COM+ singleton object.
Each client creation call will get a reference to the same instance provided
no single client is currently executing a method, when that's the case the
activation request will be suspended for a max. of the configured
"activation time-out".
Method calls are automatically synchronized (implied by JITA), each method
call will be suspended (activation time-out) whenever another client is
executing a method.

Willy.
 
D

David Browne

Willy Denoyette said:
David Browne said:
If you have two different threads, or two different processes trying to
access the object, they will be serialized. One will wait until the
other has released the reference to the object. Not just the method
calls will be serialized, but whole sequence of client code using the
object

obj = CreateObject(...)
obj.MethodA
obj.MethodB
set obj = null

will be strictly serialized. A second thread or process will block on
CreateObject until the previous thread has released the reference with
set obj=null.

This is not exactly true, that's the purpose of the JITA mechanism and
ContextUtil.SetComplete (or [AutoComplete(true)]), as soon as a method
ends the object returns to the pool where it waits to be re-activated.
Any number of clients (subject to scalability) can CREATE and KEEP a
reference a COM+ singleton object.
Each client creation call will get a reference to the same instance
provided no single client is currently executing a method, when that's the
case the activation request will be suspended for a max. of the configured
"activation time-out".
Method calls are automatically synchronized (implied by JITA), each method
call will be suspended (activation time-out) whenever another client is
executing a method.

Ok. So the serialization is at the method level. It's still absolutely
unnecessary.

David
 
W

Willy Denoyette [MVP]

Ok. So the serialization is at the method level. It's still absolutely
unnecessary.

Why? There is only one single object instance, if you allow concurrent
callers how are you going to protect you state variables?
This singleton patterns is typically used when you want to restrict the
access to an expensive external resource to a single ( or limtted number of)
caller(s) at a time.

Implementing it as a COM+ singleton offers the following important
advantages:
- Lazy instantiation (JITA)
- Auto synchronization
- Lifetime control
- Transaction control
- Security (access and instantiation)

Sure there are drawback (inherent to the singleton pattern), all depends on
the requirements and usage pattern, but as OP's original question referred
to ES, I assume he knows his requirements better than we do ;-).

Willy.
 
D

David Browne

Willy Denoyette said:
Why? There is only one single object instance, if you allow concurrent
callers how are you going to protect you state variables?
lock(obj)
{
}

This singleton patterns is typically used when you want to restrict the
access to an expensive external resource to a single ( or limtted number
of) caller(s) at a time.

Not so. You protect state variables using normal syncronization mechanisms.
And the singleton pattern is typically used to _share_ the resource. You
can have global shared resources which permit highly concurrent access (eg a
read-only DataTable), or mostly concurrent access (eg a Hashtable which you
lock during writes and iterations). You need to make it thread-safe, but
what you don't need is a big clunky framework that thinks it can do your job
for you.
Implementing it as a COM+ singleton offers the following important
advantages:
- Lazy instantiation (JITA)

C# singletons are initialized lazilly too. They are only initialized when
the class is first used. And you can even make them lazier by making
"instance" a property and creating the singleton on the first call.
- Auto synchronization
- Lifetime control
- Transaction control
- Security (access and instantiation)

COM+ does offer some useful services. If you want to use them, do. But
where the same end is more easilly acomplished with pure C#, COM+ isn't woth
the extra intelectual effort to worry about.

David
 
D

David

I would love using pure C# but my component must be "callable" from non
.Net compliant languages, VB6 and Deplhi 6 to name a few. So my
understanding is that for this reason I need COM+. Now, if there is a
better way to create C# components callable from non .net languages, I
would like to know because I really don't need any of the services
provided by COM+.
 
W

Willy Denoyette [MVP]

David Browne said:
lock(obj)
{
}
**** That way, access will be serialized at the method level too, right?
Not so. You protect state variables using normal syncronization
mechanisms. And the singleton pattern is typically used to _share_ the
resource. You can have global shared resources which permit highly
concurrent access (eg a read-only DataTable), or mostly concurrent access
(eg a Hashtable which you lock during writes and iterations). You need to
make it thread-safe, but what you don't need is a big clunky framework
that thinks it can do your job for you.

**** I never said I would use COM+ to share global resources like hashtables
or any other in-memory object.
When I'm talking about expensive resources I'm not talking about in memory
objects, I'm talking about a single external resources like Socket
connections to back-end servers or a mainframe, or DB connections, or any
resouce that is expensive to create and that could be shared by a number of
clients, and with clients I mean separate applications, NOT threads in the
same process.

That big clunky framework isn't that big, I know the disadvantages of this
kind of singleton pattern ( single point of failure, performance hotspot,
failure to scale to a large number of clients), but in some cases it does a
perfect job for me.
C# singletons are initialized lazilly too. They are only initialized when
the class is first used. And you can even make them lazier by making
"instance" a property and creating the singleton on the first call.
*** Did I say the contrary?
COM+ does offer some useful services. If you want to use them, do. But
where the same end is more easilly acomplished with pure C#, COM+ isn't
woth the extra intelectual effort to worry about.
*** Talking about intelectual effort, Do you know how many singletons are
implemented the wrong way (or should I say they are broken), and how they
are overused?
Anyway, I guess we are talking two different things here, I talk about
out-proc components (pooled COM+ objects are hosted in a separate process),
that could be used from non .NET applications like VB6 and Delphi, so they
must expose a COM interface and because OP mentioned ES, I just mentioned
the COM+ singleton, I would not suggest anything without knowing OP's exact
requirements.

Willy.
 
D

David Browne

David said:
I would love using pure C# but my component must be "callable" from non
Net compliant languages, VB6 and Deplhi 6 to name a few. So my
understanding is that for this reason I need COM+. Now, if there is a
better way to create C# components callable from non .net languages, I
would like to know because I really don't need any of the services
provided by COM+.

Right. So keep the COM junk to a minimum by exposing a lightweight,
singlecall COM interop adapter class, as per my previous post. The COM
interop adapter class is installed in COM+ and exposed to non-.net clients.


Here is a complete sample of how to expose a .NET singleton to COM clients.
Note this does not use COM+ at all.

Create a new class library project, and set the project option to register
for COM interop.

Here's the code (btw that's a new GUID, you can have it).

using System;
using System.Runtime.InteropServices;

namespace MySingleton
{

[Guid("80adff74-7124-42e6-ac2c-e19f51a47432")]
[ClassInterface(ClassInterfaceType.AutoDual)]
[ProgId("MySingleton.SingletonFacade")]
public sealed class SingletonFacade
{
public SingletonFacade() {}
public string Hello()
{
return MySingleton.instance.Hello();
}
}

public class MySingleton
{
public static readonly MySingleton instance = new MySingleton();
private MySingleton() { }
public string Hello()
{
return "Hello";
}
}
}


Build it, then create test.vbs:

set s = CreateObject("MySingleton.SingletonFacade")
msgbox(s.Hello)
set s = nothing

Save test.vbs and run it.

This is a plain jane COM interop component. When a client runs
CreateObject("MySingleton.SingletonFacade")

The CLR is loaded up into their process and the singleton exists for that
process only. If you want a system-wide singleton, then just install this
COM component in COM+ as a COM+ Server Application. This is basically as
easy as draging and droping the MySingleton.tlb into the COM+ mmc console.
Then when clients create an instance of the facade class they get a local
unmanaged COM+ proxy, and the singleton is created in a seperate COM+
process. Then all clients will share one instance of MySingleton, and they
won't have to load the CLR into their local processes.



David
 
D

David

Thank you very much.
Yes, I need a system wide Singleton. I'll install the component in COM+
as a server application.
What is the difference between using the System.Runtime.InteropServices
and System.EnterpriseServices?
 
D

David Browne

David said:
Thank you very much.
Yes, I need a system wide Singleton. I'll install the component in COM+
as a server application.
What is the difference between using the System.Runtime.InteropServices
and System.EnterpriseServices?

System.Runtime.InteropServices has the core COM interop functionality. This
is all you need for creating a plain COM interop component.

System.EnterpriseServices gives you access to additional COM+ services like
pooling, lifecycle management, security, context, etc.

COM+ can service any COM component. Some COM components are COM+ aware, and
can interact with the the COM+ services. Some COM components aren't: they
can run in COM+ but are unware of it. System.EnterpriseServices is for
making your component COM+-aware.

David
 

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