Injecting non-viewmodel objects with SimpleContainer

Topics: Bootstrappers & IoC
May 13, 2011 at 5:28 PM

For my next WP7 app, I'm going to be trying out SterlingDB as an alternative to using XML files to store list data. The SterlingDB docs recommend that you place some setup/teardown stuff in your App.xaml.cs lifecycle event handlers--launched, activated, deactivated, closed.

Instead, I'm planning to use the OnLaunched, OnActivated etc. overrides in the bootstrapper. When the app launches, the setup code fires up the database engine.

My question is around injecting the engine via SimpleContainer. So far, everything I've injected has been registered using .RegisterPerRequest() or .RegisterSingleton() and instantiated when the container first injects the dependency.

But the SterlingDB engine will be instantiated outside of the container. How can I let the container know about this object so it can handle the injection for me? Or is there a better way to tackle this that I'm not thinking of?

Coordinator
May 13, 2011 at 6:15 PM

Are you willing to take on an adventure? :) If so, you should take a look at the Trunk. The new version has some new application lifecycle functionality as well as improvements to launchers/choosers and tombstoning. The tombstoning pieces are actually "general" persistence mappings that hook into phone events and use various "storage mechanisms" to store data. They also tie into the IoC container so that everything just works. If you are interested in it, we could work together to integrate sterling with the new CM mechanism. It would be pretty cool and make some nice tests of the new APIs and blog post content. If you are interested, set up a repository somewhere for your new project and send me an email with the info. I can help you get it working. If not, no hard feelings :)

May 13, 2011 at 9:22 PM

The changes look really cool. I'm in. :) I'll set up a repo and send you the details.

May 15, 2011 at 2:59 AM
Edited May 15, 2011 at 3:25 PM

gents,

just did this today.  it works just fine in the bootstrapper overrides.  If we did as Rob indicated and provide an adapter for storage types (ala mango stuff down the road), that would allow for any store option (sql ce?) :P.

also did IoC naming convention change alittle with RegisterPerRequest() instead of PerRequest()?

 edit;  I see the changes you made by making the extension class to provide the container etc..

Morgan.

May 15, 2011 at 7:05 AM

I also use a sterling db and in the progress of converting my project to use CM. Oddly my database has been working fine during my testing but it looks like i messed with the way you startup and deactivate the engine when i added the CM bootstrapper. I actually store the database in a DatabaseManager class and activate the engine the first time it tries to access the database. what i just realised though is i'm no longer calling deactivate. everything seems fine but i get the feeling its going to cause an issue. 

I can't see the Activating / Deactivating events in my app.cs any more since using the CM project template. How did you go with this?

May 15, 2011 at 3:24 PM

you do it in the bootstrapper for the initialization of cm.  just run thru the overrides for each that are necessary.

May 16, 2011 at 10:10 AM

mvermef,

When you used the bootstrapper overrides, did you expose the database engine via a static property?

I'd still like to see a quick example of creating an object in the bootstrapper and then getting ahold of it and injecting it via the container. Would help further my understanding of IoC a bit.

Nitro, as mvermef mentioned, the Activating/Deactivating events are accessible in the bootstrapper as method overrides--OnActivating, OnDeactivating, etc. I like your idea of a DatabaseManager class.

Josh

May 16, 2011 at 11:02 AM
Edited May 16, 2011 at 11:05 AM

I did see them but wasn't sure they were the right events because i remember there being 2 more. i think it was Lanuching and Closing. I must not have been looking in the right place because i see them now.

I just expose mine through a singleton like this

 

   public class DatabaseManager
    {
        private ISterlingDatabaseInstance _databaseInstance;
        private ISterlingDatabaseInstance _stateDatabaseInstance;
        private SterlingEngine _engine;
        private SterlingDefaultLogger _logger;

        public static DatabaseManager Instance
        {
            get { return _databaseManager ?? (_databaseManager = new DatabaseManager()); }
        }
        private static DatabaseManager _databaseManager;

        public void DeactivateEngine()
        {
            if (_engine != null)
            _engine.Dispose();
            _databaseInstance = null;
            _stateDatabaseInstance = null;
        }
        public void ActivateEngine()
        {
            _engine = new SterlingEngine();
            _engine.Activate();
            _databaseInstance = _engine.SterlingDatabase.RegisterDatabase<Database>();
        }
        public ISterlingDatabaseInstance Database
        {
            get
            {
                if (_databaseInstance == null)
                    ActivateEngine();
                return _databaseInstance;
            }
        }
    }
May 17, 2011 at 6:16 PM

yes I exposed the ISterlingDatabaseInstance as a static.  Ideally, I think we want to be able take advantage of the CM StorageMechanism (based on the lastest code), thus allowing us to use the container, but I don't think inheriting from that would allow us to make it work correctly. Something along the lines of inheriting a IPhoneService

Although the code sample that Sterling has for running it as a service works just fine too..  But again the initialization is done solely through the db, nothing is done with CM in this bootstrapping case.

 

Coordinator
May 17, 2011 at 9:39 PM

I'd be highly interested in making sure that sterling can be represented as a storage mechanism. I don't have the bandwidth to do it myself, but I'm happy to help anyone who wants to give it a shot. Set up a repository somewhere and give me access and we can collaborate on it. It would really help me ensure that CM's new API's are designed well enough to support those types of extensions.

May 17, 2011 at 11:09 PM

I'm not sure i fully understand what you want to test, is there a new feature coming up for storage? The sterling code is fairly stand alone. You just need to initialize it, deactivate it and call the CRUD methods on the engine. so i'm not to sure how this ties in with CM?

Coordinator
May 17, 2011 at 11:47 PM
Edited May 17, 2011 at 11:47 PM

The Trunk has some new features for WP7 around tombstoning that allow object persistence to tie into the phone's tombstoning and app close behavior as well as the IoC container. OOTB I am providing persistence in PhoneState and in Isolated Storage. It's extensible, so you build a sterling provider or one for Mango's local database. Have a look at the HelloWP7 sample in the trunk for an example. It may not make sense at all to try and write a provider for Sterling, but I wanted to check.

May 18, 2011 at 1:53 AM
Edited May 18, 2011 at 1:55 AM

yea been looking at it and I don't think the way Sterling is written it would be beneficial for a provider or be tied into the IoC or soon to be on phone db ( sql ce phone edition?).  The IStorageMechanism is nice but it doesn't lend itself well for Sterling imo.

Using IApplicationLifetime works just fine for a class to call / kill / tombstone Sterling pretty well.

Coordinator
May 18, 2011 at 2:05 AM

Ok. Thanks for checking.

Jun 8, 2011 at 7:19 PM
Edited Jun 8, 2011 at 7:22 PM

so I had a wild hair today and I have setup Sterling to work with the container.  I created an interface to be the base and then register it with the IoC as an instance;

   public interface ISterlingInstance
    {
        void Activate();
        void Deactivate();

        ISterlingDatabaseInstance Database { get;}
    }
public class SterlingService : ISterlingInstance
{
        private SterlingEngine _engine;

        private Guid _loggerId = Guid.Empty;

        public ISterlingDatabaseInstance Database { get; private set; }

        private SterlingDefaultLogger _logger;


        public SterlingService()
        {

        }

        public void Activate()
        {
            if (DesignerProperties.IsInDesignTool)
                return;

            if (Debugger.IsAttached)
            {
                _logger = new SterlingDefaultLogger(SterlingLogLevel.Verbose);
            }

            _engine = new SterlingEngine();
            _engine.Activate();

            Database = _engine.SterlingDatabase.RegisterDatabase<YOUR_DB>();
            //TRIGGERS HERE ETC...
       }

      public void Deactivate()
      {
            if (Debugger.IsAttached && _logger != null)
            _logger.Detach();

            _engine.Dispose();

            Database = null;
            _engine = null;
       }

}
I then used the overrides for OnActivate(), OnDeactivate, OnLaunch, OnClose    
then place Activate calls in OnActivate / OnLaunch  and then call Deactivate calls in OnDeactivate / OnClose
it works as expected for tombstoning and flushing...
I did some other stuff with this to facilitate Repository Pattern for object access but its not necessary to implement.. 
This for those that wanted Sterling and injectable with the container....
-Morgan