-
Notifications
You must be signed in to change notification settings - Fork 5
WpfBaFactory Class
When the bundle starts, a factory is used to build out the BA. The BootstrapperApplicationFactory
assembly attribute informs the bundle which class is the factory.
[assembly: BootstrapperApplicationFactory(typeof(WpfBaFactory))]
You must supply a factory that inherits from BaseBootstrapperApplicationFactory
and override the Create method to build up and return your bootstrapper app. Since this is a factory, it's an appropriate place to build up the models your app needs.
There are a lot of events exposed by our bootstrapper application, BootstrapperApp
. This is a good place to subscribe to them.
Warning
You should not construct any user interface elements when building out your bootstrapper app. Do not create any windows. Do not associate a Dispatcher with the thread that the factory's Create method is running in. You'll have to build out your UI once your bootstrapper app is running.
You'll notice the code in the Create method is wrapped in a try...catch
. This will be a recurring theme that you'll see a lot. Threads will frequently be used to perform tasks. You should assume nothing about the thread any given method is running in. All shared state should be accessible using thread safe techniques. Every event handler should handle its own exceptions, and so should any method that is executed by the WiX framework. In addition to this, I also suggest setting up a handler for unhandled exceptions. That doesn't need to happen until your BA is running, so I use the Dispatcher.UnhandledException
event to deal with these.
If you're handling exceptions in your code, where will these unhandled exceptions come from? You can trigger these by supplying the WiX framework with data it's not designed to handle. WiX processes running in the background can trigger these. Logging these exceptions will be useful for debugging.
Looking in the Create method, you'll see a uiFacade. You'll also notice it's injected into a model.
var uiFacade = new WpfFacade(new Log(engine), commandInfo.Display);
var model = new Model(engine, commandInfo, uiFacade);
That model is "The Model" in our MVVM pattern. But what's a UI facade? The facade pattern allows us to expose only the needed functionality of our selected UI framework. This helps to organize our code. We'll cover this in more depth when reviewing the WpfFacade
class.
As for the model, it's a convenience class that puts all the WiX models, shared app state, and UI access in one place. It also exposes some convenience methods. It's easier to inject this into view models and the rest of the BA code instead of separate WiX models.
After constructing the BA, some methods are called to subscribe to events.
SubscribeCancelEvents(ba, model);
SubscribeProgressEvents(ba, model);
SubscribeDetectEvents(ba, model);
SubscribePlanEvents(ba, model);
SubscribeApplyEvents(ba, model);
These are split into the detect, plan, and apply phases, but there are also a couple that deal with cancellation and progress.
If you look closely at these methods, you'll notice they all instantiate a class that handles specific events, but references to those instances aren't maintained. Each of these has the model injected into them. These event handlers deal with the majority of detecting and managing the packages in the bundle during the install.