MEF is a way tying things (methods, instances) together, perhaps DynamicProxy and Krzysztof's blog could help?
http://kozmic.pl/archive/2009/04/27/castle-dynamic-proxy-tutorial.aspx Qi4J <http://qi4j.org/> has a similar concept regarding composites and many layers making up a method; perhaps you could apply similar layers with dynamic proxy, one for each type of entity (BookProduct, CarProduct .), or have a round robin sort of pool of this objects, with the tenant's key as a hash for which bucket to take the proxy from? A plugin could then be a mixin, with dynamic proxy creating a new proxy for it; as long as you don't do thousands of turn on/off of the plugins constantly, the generated code would probably not increase the memory footprint too much. You could provide a key for each sort of mixin/interceptor and then keep e-tags of the proxys where the e-tag denotes the combination of tenant's interceptors that the proxy implements? Another way to enable/disable plugins at runtime, could perhaps be to implement the command pattern, typed for each business operation that varies depending on client (now not talking entities) - then you could perhaps do a "ResolveAll<IAddOrderOperation>()" on the IoC container, where IAddOrderOperation : IEquatable, IComparable, push them into a list, sort it and then do list.ForEach(applyOp), to your state? You could write your own ForEach method with multiple exists (invalid op, invalid rule, invalid state, dependency failed, whatever), similar to how the Maybe monad works (or the Result<TOut,Tex>whereTOut:IOutcome, TEx :Exception-monad?). Taking the monad concept further, perhaps you could have a collection for each tenant, of transformer methods that mutate the state in the monad (similar to multiple interceptors, but functional)? These functions could be resolved for using MEF, or through interfaces implementing only one method similar to how functors work in OCaml? Just some ideas based on the abstract concept of multi-tenancy. :) Cheers, Henrik From: [email protected] [mailto:[email protected]] On Behalf Of Jan Limpens Sent: den 23 februari 2010 00:33 To: [email protected] Subject: Re: Extensible Monorails project Currently I am trying to get this partially done via dynamic actions, but I'd want to hear more about this, hammett :) ! On Mon, Feb 22, 2010 at 5:41 PM, Alex Henderson <[email protected]> wrote: I'd love to see a blog post on this... I'm treading similar water developing extensible applications in monorail. I might start blogging about my experiences soon, just so I can get some feedback on our current approach and ways to improve it (especially around MEF + IOC Container, and approaches for handling disabling/removing plugins are runtime - something we currently do have working, but it's not pretty). Cheers, - Alex On Tue, Feb 23, 2010 at 7:22 AM, hammett <[email protected]> wrote: It's a complicated problem. I can see a few ways to solve. but the price is increased complexity. Will try to cover this in a blog post given that the topic is open ended extensibility.. On Mon, Feb 22, 2010 at 8:44 AM, Jan Limpens <[email protected]> wrote: > Hello! > > I have an administrative interface done in MR for a single client doing all > kind of crud and more operations using explicit services and or explicit or > implicit Daos (IArticleDao and IDao<Article, long>) resolved from Windsor. > > Now this project has grown and I will have to make this application > extensible (and am breaking my head over how to attack this). Different > tenants will have different extensions to the base domain. For instance a > customer who sells cakes will need different properties on their Article > implementation than customer who will sell toys. Domain and NHibernate wise > I think I've got this handled. > > From what I see I will have to take care of the full implementation of a > certain feature crossing typical layers. So one new feature concerning one > or a set of changes to the domain model should take care of > > View and view logic in JavaScript and brail > Controller extensions to the base Controller > Service extensions... > > in the form of one dll - in the ideal case - dropping it in a certain place > should autowire it somehow, but this can wait. > > What I really am concerned about are the extension points I can provide from > the administrative interface. > > A simple case: > > [return: JSONReturnBinder] > [Transaction(TransactionMode.Requires)] > public virtual IList<SimpleArticle> FullTextSearchAsJson(string > fragment, int categoryId, int productGroupId, string orderBy, > > SortDirection direction, int maxResults, bool isActive, decimal from, > decimal to) > { > Func<Product, object> func = null; > switch (orderBy.ToLowerInvariant()) > { > case "name": > func = (x => x.Name); > break; > case "id": > func = (x => x.Id); > break; > } > var priceRange = new PriceRange(from, to - from); > > var articles = articleDao.Find(fragment, categoryId, > productGroupId, 0, func, direction, maxResults, 0, isActive, priceRange); > var result = articles == null ? null : new > List<Product>(articles); > if (result == null) return null; > var link = new LinkHelper(Context); > return result > .Select(article => new SimpleArticle(article.Id, > article.Name, > article.Key, > link.Article(article))) > .ToList(); > } > > now we extend the Article class with Properties string ISBN { get; set; } > and bool HasISBN { get; } and it becomes the BookArticle class. The above > method should also output those two fields. > > So to have code reuse, > > I'd probably refactor out the actual query part, > taking the dao as a parameter, > returns my new article sub class > and the I'd use an extended SimpleArticle to present my items. > luckily there is no real view involved, because I have absolutely no idea on > how to introduce code reuse in that area. I wished, my entities > automagically would create their forms for themselves, but this cannot work > for more complicated entities, I suppose. > > While all of this certainly is doable, it is very non-frameworkey and I hate > all the coupling this introduces. And the best bet for code reuse in the > view area for now is relying on the merge feature of my source control. > > Anyone wrote something clever about this? Or is inclined to pass me some > good pointers here and now? > > Thanks! > > -- > Jan > > -- > You received this message because you are subscribed to the Google Groups > "Castle Project Users" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected] <mailto:castle-project-users%[email protected]> . > For more options, visit this group at > http://groups.google.com/group/castle-project-users?hl=en. > -- Cheers, hammett http://hammett.castleproject.org/ -- You received this message because you are subscribed to the Google Groups "Castle Project Users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected] <mailto:castle-project-users%[email protected]> . For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en. -- You received this message because you are subscribed to the Google Groups "Castle Project Users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected] <mailto:castle-project-users%[email protected]> . For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en. -- Jan -- You received this message because you are subscribed to the Google Groups "Castle Project Users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en. -- You received this message because you are subscribed to the Google Groups "Castle Project Users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/castle-project-users?hl=en.
