I just finished working through the final kinks (that I know of).
You can instantiate the application server and set it up any way you want to. You do not need the setup objects below. They are there for, hopefully, convenience and simplicity. The Build method on the ApplicationServerSetup object instantiates an appserver, then copies all the stuff from the setup objects to the appserver.
There are 3 setup pre-packaged setups:
There is an extension method for each. These examples are using node.
The only item you must specifically set is the ObjectFactory. The one I provide is based on Unity. I put all of that into a different assembly so that if someone wants to use something else, they won’t have the unity references polluting the core project.
The unity extension method and objects are not in the same assembly as the setup objects, so I can’t default it to unity because it doesn’t have the reference. The project that uses the app server will have a reference to the unity assembly if that’s what it wants to use.
var appserver = new ApplicationServerSetup() .AsNode() .ObjectFactorySetup.UseUnity().Setup .Build(); var appserver2 = new ApplicationServerSetup() .BusSetup.UseLocalBus().Setup .CommandProcessorManagerSetup.UseDefault().Setup .FeatureManagerSetup.UseDefault().AddApplicationHostFeature().UseAllFolders().SetRootFolder("Applications").Setup .ObjectFactorySetup.UseUnity().Setup .ObjectRepositorySetup.UseDefault().Setup .TypeCacheSetup.UseDefault().Setup .Build();
The first example is the bare-minimum to get a node going. The second expands all of the optional components. So far there is only one implementation for each major component.
The application server can contain one or more features. You can see in the middle that I’m adding a feature called Application Host Feature. It has a dependency that give a list of application configuration objects. It will then create apps for each of those objects. I have two implementations of that dependency. The first, shown, will create one application for every folder within the specified root folder. The other requires you to specify exactly which ones you want.
It defaults to UseAllFolders. If you use AsNode(), it sets it up for you. Then you can tweak the settings if necessary. Furthermore, every setup object has a default builder, so you don’t have to initialize everything explicitly
If you call the same Use more than once, it doesn’t reset it. IE: If you want to get back to the bus, you can do UseLocalBus() again, and it won’t overwrite the existing bus setup. It will see that the type has not changed and will return the existing setup object.
That is handy because these objects all have their own custom properties and methods, but they are stored as their base type. BusSetup.UseLocalBus() will return the correct type you are looking for. But, if later you go to BusSetup.Builder, then all you get is an IBuilder, so then you would have to cast it appropriately. Instead, just use UseLocalBus() again, and it will get the existing object and cast it for you.
The SETUP at the end of each line brings you back to the root ApplicationServerSetup object.
I’m not an expert with fluent interfaces. I may look at this later and bow my head in shame, but at least for the moment, it does what I need it to. In my opinion, it doesn’t matter how well something works if it takes forever to get it up and going. You can now simply create a hub, node or application. If you need something fancier, you can do that too. If the fluent interface doesn’t support something you want, you can add it to share with others (via extension methods and subclasses), or you can just add what you need to the server itself. I am now satisfied with how this balances simplicity and flexibility.
There will be a lot more things to add as I go, but the pattern has been established, so I can get back to working on the app server itself.
If anyone is interested in how the setup objects work, drop a comment and I will elaborate.