Another View/Viewmodel location strategy question

Topics: Conventions, Extensibility, Feature Requests, Framework Services
Dec 16, 2011 at 1:09 AM
Edited Dec 16, 2011 at 1:42 AM

This issue came up when deanvmc suggested that I add a statement in the documentation for the new type mapping methods about whether or not the mappings were additive. I said that they were additive, but it occurred to me that they were additive only in a sense that each transformation rule had an opportunity to be evaluated (i.e. any custom rules that you add don't remove the existing ones). But the evaluation process is "short-circuited" once a matching rule is found. In other words, once a pattern is matched, then only the possible target types (i.e. the resultant "transformed names") associated with that specific rule are considered. I say "target types" (plural), because there can actually be multiple target types for a given transformation rule. We needed to be able to associate multiple target types with a given transformation rule in order to support the use of an IoC container (i.e. need to be able to check for both concrete types and interfaces). Therefore, while only one transformation rule could ever apply to any given location attempt, the NameTransformer could still return several target types.

However, on the back-end of the type location process, when searching for the target types within the AssemblySources, the locator classes return the first match from what could be several possibilities. It occurs to me because of the "safety net" of returning only the first matching type within the AssemblySources, it's not entirely necessary to short-circuit the rule evaluation process on the front-end. Regardless of how many of the transformation rules could actually apply and how many target types result from applying all of those rules, only one type (or none) will ever be returned by the locator classes.

So my question is this: should we eliminate of the short-circuit behavior (of the rule evaluation) described above?

This could be done by the removal of a single line of code. If you think this would be a breaking change, we could optionally control this through a property on the NameTransformer and default it to the short-circuit behavior. This would be a trivial change to implement as well.

What do you all think?

 

Dec 16, 2011 at 9:24 AM

Do you mean remove it both front and back or remove the redundancy?

Dec 16, 2011 at 2:52 PM

Just the front (rule evaluation).

Dec 19, 2011 at 2:35 PM

Rob, do you have an opinion on this?

Coordinator
Dec 19, 2011 at 9:14 PM
Edited Dec 19, 2011 at 9:14 PM

It's fine if we eliminate the short circuit. *However*, in the case where interfaces would be returned, they need to be first in the list, before any concrete types. Othwise the locator may end up accidentally trying to instantiate a type the wrong way.

Dec 19, 2011 at 9:22 PM

What is your feeling about being able to control the short-circuit behavior through a property on the NameTransformer? If you're fine with that, I could have it default to this new behavior and allow people to change the property value to retain the current short-circuit behavior.

Regarding the interface issue, I can definitely reorder how the possible target types are added to the collection, and it should dictate the order in which they are searched through the AssemblySource. 

Dec 19, 2011 at 10:31 PM

I went ahead and added the ability to change the short circuit behavior through a property (NameTransformer.UseEagerRuleSelection). This code demonstrates how it will work:

string typename, result;
            
//Return results from the built-in rules
typename = "SomeNS.ViewModels.More.TestViewModel";
result = String.Join(", ", ViewLocator.TransformName(typename).ToArray());
//SomeNS.Views.More.TestView, SomeNS.ViewModels.More.TestView, SomeNS.ViewModels.More.TestView
//Transformations from all matching rules are returned -- even if some transformations are duplicates
//This is new the default behavior

//Map to two possible target subnamespaces
ViewLocator.AddSubNamespaceMapping("ViewModels", new string[] {"MyViews1", "MyViews2"});
result = String.Join(", ", ViewLocator.TransformName(typename).ToArray());
//SomeNS.MyViews1.More.TestView, SomeNS.MyViews2.More.TestView, SomeNS.Views.More.TestView, SomeNS.ViewModels.More.TestView, SomeNS.ViewModels.More.TestView
//Again, transformations from all matching rules are returned   

//Return transformations from only the first matching rule
ViewLocator.NameTransformer.UseEagerRuleSelection = false;
result = String.Join(", ", ViewLocator.TransformName(typename).ToArray());
//SomeNS.MyViews1.More.TestView, SomeNS.MyViews2.More.TestView
//This is the current behavior