Singleton strategy

Topics: CAB & Smart Client Software Factory
Feb 9, 2006 at 12:28 PM
originally posted by: jrimpo

Say I have an object that I am going to create via the Items.<AddNew> and I want to enforce that it be a singleton. Is there a way that I can decorate the class that will enforce the SingletonPolicy strategy built into the ObjectBuilder?

I am building a "Project" class (just a plain ol' class, not a smart part, not a service) - and I know how to implement it so that it ~will~ be a singleton, but I really want to use the ObjectBuilder's strategy.
Feb 9, 2006 at 12:51 PM
originally posted by: WalkingDisaster

You could decorate your service to AddOnDemand, then use a static boolean and use it to enforce that it cannot be instantiated twice. If you never construct it manually, ObjectBuilder will construct it the first time the service is injected.
Service(typeof(IWhateverService), AddOnDemand = true)
More simply, though, you can hide the implementation of your service by implementing the service interface in a separate dll that is referenced by CAB on start.

For your "Project" class, you can declare it as your WorkItem type when you define your application class. Then it will become your RootWorkItem.
class MyApplication : FormShellApplication<ProgramWorkItem, MyForm>
Feb 10, 2006 at 7:54 AM
originally posted by: jdressel

I hope not to confuse, I was some time ago (last month ;) I did this
The Items (ManagedObjetCollection) behaves differently than the ServicesCollection in that Services, when created are by default singletons if the Type you register as is != the Type you're creating. re: BuildFirstTimeItem() methods of each for the differences. You can get the Items collection to behave as a singleton... I think.... if you builder.Policies.Set a SingletonPolicy for your Type with the Builder of your workitem (WorkItem.InnerBuilder).
For example:

string KNOWN_ID = "ID";
ISingletonPolicy singletonPolicy = new SingletonPolicy(true);
WorkItem.InnerBuilder.Policies.Set<ISingletonPolicy>(singletonPolicy, typeof(Foo), KNOWN_ID);

Problem is, you need to know the ID up front. I have some UnitTests I wrote to understand all this, but this snippet is where the rubber hits the road. I didn't do this in the context of the managed collections, but rather with the 'raw' Builder and BuilderContext classes, but I think this should still work.

HTH
Feb 10, 2006 at 8:12 AM
originally posted by: WalkingDisaster

I think you might be thinking a little too boilerplate in your implementation. If you have the appropriate attribute on your service class:
Service(typeof(IWhateverService), AddOnDemand = true)
Then the first time you try to inject this service into a class being built by ObjectBuilder, it will create itself. The key is to reference it by the interface type:
// ObjectBuilder matches the IWhateverService setter to the Service attribute
// that was constructed with typeof(IWhateverService) as the first parameter
ServiceDependency
public IWhateverService WhateverService
{
get { return this.whateverService; }
set { this.whateverService = value; }
}

In your unit tests, you will not have to use ObjectBuilder at all, you simply manually insert your mock object for the service interface during the setup phase (see http://www.nmock.org/ for a good mock framework in .Net).