View Resolution Inconsistency

Topics: Bootstrappers & IoC
May 25, 2011 at 7:49 PM

I noticed that there's an inconsistency in the conventions for View resolution as described here.

In the code to locate the View based on the ViewModel name, you simply remove "Model":

var viewTypeName = modelType.FullName.Replace("Model", string.Empty);

So, if the ViewModel is named "SomethingViewModel" the View name resolves to "SomethingView".

Aside: Isn't this kind of dangerous since this would choke on a ViewModel named something like "ModelTrainViewModel" since the resolved View name would be "TrainView" rather than "ModelTrainView"?

In the code to locate the ViewModel based on the View, there's a check to see if the View name ends with a "View". If it does, then CM just tacks on a "Model". Otherwise, it tacks on "ViewModel". Therefore, a View named "SomethingView" OR simply "Something" would be  registered to the ViewModel named "SomethingViewModel".

IOW, if you call container.RegisterAllViewModelsForPages() in your bootstrapper, you won't need to end the name of all your Views with "View". However, if you call container.RegisterSingleton() or container.RegisterPerRequest(), then your View name MUST end with "View".

Coordinator
May 25, 2011 at 8:27 PM

I've made some improvements to this area in the last couple of days. Regardless, I'm not sure if there is a foolproof way to do this. That's one of the reasons that you can override the mapping function with your own. This is generally one of the most customized areas of the framework, so it's really easy and I tend not to worry if I can't make 100% of the cases work. That said, if you find a better way to implement the name mapping, please let me know. You can either post code here or fork the project and send me a pull request.

May 25, 2011 at 11:18 PM

Well, the first thing I can suggest is to use regular expressions to eliminate the overzealous string replacement that I mentioned above:

var viewTypeName = System.Text.RegularExpressions.Regex.Replace(modelType.FullName, "ViewModel$", "View"); //replaces only if string terminates with "ViewModel"
May 26, 2011 at 12:25 AM

I forked the project and created a clone. When I looked at the code, I noticed that you changed the code a bit:

            var viewTypeName = modelType.FullName.Substring(0, modelType.FullName.IndexOf("`") < 0
                ? modelType.FullName.Length
                : modelType.FullName.IndexOf("`")
                ).Replace("Model", string.Empty);

How is the grave accent ("`") character used in the ViewModel naming convention? 

Coordinator
May 26, 2011 at 12:45 AM

It detects a generic type.

May 26, 2011 at 1:32 AM

Is this correct?

            if(viewTypeName.Contains("Page") && viewTypeName.EndsWith("View")) {
                viewTypeName = viewTypeName.Remove(viewTypeName.Length - 4);
            }

            if (context != null)
            {
                viewTypeName = viewTypeName.Remove(viewTypeName.Length - 4, 4);
                viewTypeName = viewTypeName + "." + context;
            }

If the ViewModel name is something like ElectronicPagerViewModel, then the net result (after the initial removal of "Model") will be "ElectronicP" + "." + context, if context != null.

i.e. ElectronicP.SomeContextName

I'm guessing that this isn't the result you intended. What is this code trying to do, BTW? Are you trying to leave a string-terminating "Page" in the View name if context == null, but remove the string-terminating "Page" if context != null?

 

Coordinator
May 26, 2011 at 1:49 AM

Hmm. I just made the "Page" check addition do to some WP7 naming scenarios, but I think I goofed up, as you have pointed out. Basically, I need to cover the following scnearios:

MainPageViewModel => MainPage

ShellViewModel => ShellView

It might be better to build up a list of "possibilities" and simply take the first match. That's what I am doing in the ViewModelLocator now, like this:

            var typeName = viewType.FullName; //ex. ShellView

            if(!typeName.EndsWith("View"))
                typeName += "View";

            var possibleNames = new List<string>();
            var baseName = typeName.Replace("View", "ViewModel"); //ex. ShellViewModel

            if(searchForInterface) {
                possibleNames.Add(MakeInterface(baseName)); //ex. IShellViewModel
                possibleNames.Add(MakeInterface(baseName.Remove(baseName.LastIndexOf("ViewModel")))); //ex. IShell
            }
            else {
                possibleNames.Add(baseName);
            }

            var viewModelType = (from assmebly in AssemblySource.Instance
                                 from type in assmebly.GetExportedTypes()
                                 where possibleNames.Contains(type.FullName)
                                 select type).FirstOrDefault();

            return viewModelType;

Thoughts?

May 26, 2011 at 2:10 AM
Edited May 26, 2011 at 2:12 AM

I'm not understanding when the viewTypeName + "." + context comes into play here, but I think using RegEx.Replace() will definitely make these string transforms much safer.

            string replaceStr, matchStr;

            if (System.Text.RegularExpressions.Regex.IsMatch(viewTypeName, "PageViewModel$"))
            {
                matchStr = "PageViewModel$";
                replaceStr = "Page";
            }
            else
            {
                matchStr = "ViewModel$";
                replaceStr = "View";
            }

            if (context != null)
            {
                replaceStr = "." + context;
            }

            viewTypeName = System.Text.RegularExpressions.Regex.Replace(viewTypeName, matchStr, replaceStr);

This code will cover the following cases:

When context == null:

  • MainPageViewModel => MainPage
  • ShellViewModel => ShellView
  • ElectronicPagerViewModel => ElectronicPagerView
  • ElectronicPagerPageViewModel => ElectronicPagerPage

When context = "SomeContext":

  • MainPageViewModel => Main.SomeContext
  • ShellViewModel => Shell.SomeContext
  • ElectronicPagerViewModel => ElectronicPager.SomeContext
  • ElectronicPagerPageViewModel => ElectronicPager.SomeContext

Is this what you were after?

Coordinator
May 26, 2011 at 2:22 AM

I should really learn to write some Regex :) Yes, that's what I'm after. That would be a nice improvement. FYI, context is used to support multiple views over the same view model. So, you can do something like this:

<ContentControl cal:View.Model="{Binding ActiveItem, Mode=TwoWay}" cal:View.Context="Summary" />

<ContentControl cal:View.Model="{Binding ActiveItem, Mode=TwoWay}" cal:View.Context="Edit" />

I don't use it terribly often, but it's quite powerful, especially since you can databind the Context property.

I'll try to get your Regex improvements in...probably tomorrow. Can you think of any improvements to the ViewModelLocator as well? or is that ok?

May 26, 2011 at 4:43 AM

I'll see if I can get my head around the ViewModelLocator class. As for the ViewLocator class, I have an idea about how to make the string transforms more flexible to handle more cases in the future. I'll test it out, and I'll check the changes into my fork later.

May 26, 2011 at 6:25 AM
Edited May 26, 2011 at 6:27 AM

I tested this out, and there's going to be a problem with one of the example projects, namely the HelloWP7 project, which has a View called PageTwo and a ViewModel called PageTwoViewModel. Following the convention mentioned above, the resolved view would be PageTwoView. Had the ViewModel been called SecondPageViewModel, then the resolved View would have been SecondPage, according to the transform rules above.

I checked all the sample projects, and luckily, HelloWP7 is the only project with this oddball View.

So now, the convention for going from View => ViewModel should be:

<BaseName>Page => <BaseName>PageViewModel

<BaseName>View => <BaseName>ViewModel

Is that correct?

Coordinator
May 26, 2011 at 1:32 PM

It could also be:

<BaseName>View => <BaseName>

Plus we need to look for interfaces. Because when going from View to View Model, it's more likely that the VM may be registered by an interface in the IoC container, rather than the concrete type.

Regarding the View Locator, it would also be cool to be able to go from <BaseName> to <BaseName>View

May 26, 2011 at 3:36 PM

When would <BaseName>View => <BaseName> be used?

This case could be handled by adding this line to the static constructor of ViewLocator (in my pull request):

AddTransformPair("View$", String.Empty);

Locally, I handled the oddball case of HelloWP7 by adding this line to the Configure() method of HelloWP7Bootstrapper:

            //Added because it goes against all of the standard transform conventions
            ViewLocator.AddTransformPair("PageTwoViewModel", "PageTwo");

            container.RegisterPhoneServices();
            container.PerRequest<MainPageViewModel>();
            container.PerRequest<PageTwoViewModel>();
            container.PerRequest<TabViewModel, TabViewModel>();
            ...

As for interfaces, what would the transform convention be?

I<BaseName>ViewModel => ???

Coordinator
May 26, 2011 at 4:20 PM

For interfaces we are going from the view to a View Model name. So something like:

ShellView => IShellViewModel, IShell, Shell or ShellViewModel

MainPage => MainPageViewModel, IMainPageViewModel (This is what VS names things by default, which is why I'd like the convention, as well as the reverse from MainPageViewModel => MainPage or MainPageView)

MainPageView => MainPageViewModel, IMainPageViewModel

Coordinator
May 26, 2011 at 4:21 PM

If supporting a View without the word View is going to cause significant complexity or unpredictability, we can just avoid it and change the sample. It's probably a good idea anyways so that we keep WP7 naming conventions consistent with SL and WPF. Let me know what you think.

May 26, 2011 at 11:15 PM
Edited May 26, 2011 at 11:21 PM
EisenbergEffect wrote:

If supporting a View without the word View is going to cause significant complexity or unpredictability, we can just avoid it and change the sample. It's probably a good idea anyways so that we keep WP7 naming conventions consistent with SL and WPF. Let me know what you think.


What I checked into my fork can handle this case through a custom convention as I mentioned above.

For View resolution would you say that these conventions would cover all (or most) of the cases:

1. <BaseName>ViewModel => {<BaseName>View, <BaseName>.<ContextName>}

examples:

  • CustomerViewModel => CustomerView
  • AccountViewModel => AccountView
  • CustomerViewModel => Customer.Context
  • AccountViewModel => Account.Context

2. <BaseName><ViewSynonym>ViewModel => {<BaseName><ViewSynonym>, <BaseName>.<ContextName>}

examples:

  • CustomerPageViewModel => CustomerPage
  • CustomerFormViewModel => CustomerForm
  • CustomerScreenViewModel => CustomerScreen
  • CustomerPageViewModel => Customer.Context
  • CustomerFormViewModel => Customer.Context

Considering both conventions above, the View name MUST end with either "View" or any synonym of "View" (e.g. Page, Form, Screen, etc.) UNLESS it's for a data context. Do you think that's an OK requirement?

Also, would you say that, unlike the ViewModel resolution, View resolution should ALWAYS be determinate? Or do you think that there might be a use case where it could be indeterminate, and it would be better to search the assembly for the first match?

 

May 26, 2011 at 11:20 PM
Edited May 26, 2011 at 11:21 PM
EisenbergEffect wrote:

For interfaces we are going from the view to a View Model name. So something like:

ShellView => IShellViewModel, IShell, Shell or ShellViewModel

MainPage => MainPageViewModel, IMainPageViewModel (This is what VS names things by default, which is why I'd like the convention, as well as the reverse from MainPageViewModel => MainPage or MainPageView)

MainPageView => MainPageViewModel, IMainPageViewModel

OK. So ViewModel resolution is indeterminate. You have no choice but to search the assembly for a match. I think this can still be made extensible through the use of a collection of regular expression transform definitions like in the code that I checked in.

But getting back to the View resolution, is there any use case where you'd need to resolve the View from an interface of a ViewModel?

Coordinator
May 27, 2011 at 2:18 AM

No need to resolve a view from an interface. We will always have the concrete model type, so we can determine a view. We don't bother looking for view interfaces, because it's usually a bad idea to resolve your view from IoC anyways. When we start with the view, however, it might be that the determined VM cannot be created, but that we need to find the interface and resolve it from the IoC container. Does that make sense?

May 27, 2011 at 2:23 AM
Edited May 27, 2011 at 2:25 AM
EisenbergEffect wrote:

No need to resolve a view from an interface. We will always have the concrete model type, so we can determine a view. We don't bother looking for view interfaces, because it's usually a bad idea to resolve your view from IoC anyways. When we start with the view, however, it might be that the determined VM cannot be created, but that we need to find the interface and resolve it from the IoC container. Does that make sense?


I guess. ;)

Something I'm not clear about is this:

ShellView => IShellViewModel, IShell, Shell or ShellViewModel

I understand that an interface might not follow the naming conventions for a ViewModel (i.e. always ending with "ViewModel"), but in what use case would a concrete class of a ViewModel not be named in the "traditional" way?

BTW, I'm really close to checking in an update to my fork that will make both the View resolution and ViewModel resolution very flexible and customizable using some really powerful regular expression transforms.

Coordinator
May 27, 2011 at 3:22 AM

That particular case is not important really. We could do without it. Thanks for working on this. It's a great improvement.

May 27, 2011 at 8:26 AM

Since you are in a flow of modification in this area, how about defining a simple static property to hold the "." separator used to concatenate context?
This way we can easily customize the convention to get rid of the nested namespace - which "accidentally" I often do... :-) 

 

Coordinator
May 27, 2011 at 1:34 PM

I'm sure we could manage that :)

May 27, 2011 at 2:22 PM
Edited May 27, 2011 at 3:11 PM

OK. I sent you a pull request. I was not able to test the ViewModel resolution, since I'm not exactly sure how it's used. However, below is a code snippet that I used to test the functionality by getting references to the NameResolutionManager instances maintained by the ViewLocator and ViewModelLocator classes. Normally, you'd get a reference to the NameResolutionManagers to add your own custom conventions, but in my test code it's used to also get a list of the resolved names directly, which the ViewLocator/ViewModelLocator would normally do. Here is the sample code:

var vmgr = ViewLocator.GetViewResolutionManager();

//Add special convention for ViewModels that start with "Page". Note the use of global filter pattern (3rd argument).
vmgr.AddTransformConvention("(?<prefix>(^Page))(?<basename>.*)(?<suffix>(ViewModel$))", "${basename}${prefix}View", "^Page");

Func<string, string>  funcVGetReplaceStr = (r) => { return "." + "DataContext"; };

var vnamelist1 = String.Join(",", vmgr.GetResolvedNameList("MainPageViewModel").ToArray());
//MainPage

var vnamelist2 = String.Join(",", vmgr.GetResolvedNameList("CustomerViewModel").ToArray());
//CustomerView

var cvnamelist1 = String.Join(",", vmgr.GetResolvedNameList("MainPageViewModel", funcVGetReplaceStr).ToArray());
//Main.DataContext

var cvnamelist2 = String.Join(",", vmgr.GetResolvedNameList("CustomerViewModel", funcVGetReplaceStr).ToArray());
//Customer.DataContext

var custvnamelist1 = String.Join(",", vmgr.GetResolvedNameList("PageOneViewModel").ToArray());
//OnePageView

var vmmgr = ViewModelLocator.GetViewModelResolutionManager();

//Function for exclusion of interfaces (interfaces are included by default)
Func<string, string> funcVMGetReplaceStr = (r) =>
{
    if (r.StartsWith("I$")) //It's an interface transform so make it something impossible to exist
    {
        return String.Empty;
    }
    return r;
};

var vmnamelist1 = String.Join(",", vmmgr.GetResolvedNameList("MainPage").ToArray());
//MainPageViewModel,IMainPageViewModel

var vmnamelist2 = String.Join(",", vmmgr.GetResolvedNameList("CustomerView").ToArray());
//CustomerViewModel,Customer,ICustomerViewModel,ICustomer

var ivmnamelist1 = String.Join(",", vmmgr.GetResolvedNameList("MainPage", funcVMGetReplaceStr).ToArray());
//MainPageViewModel,<blank>

var ivmmamelist2 = String.Join(",", vmmgr.GetResolvedNameList("CustomerView", funcVMGetReplaceStr).ToArray());
//CustomerViewModel,Customer,<blank>,<blank>
Coordinator
May 27, 2011 at 2:39 PM

That looks pretty cool. I'll have a look at the pull request this weekend and see about getting it integrated. Nice work!

May 27, 2011 at 3:13 PM

Oops. I realized that I screwed up the comment for this line:

var custvnamelist1 = String.Join(",", vmgr.GetResolvedNameList("PageOneViewModel").ToArray());
//PageOneView

It should read //OnePageView. This special case wouldn't be very interesting, otherwise. Corrected in original post.

May 27, 2011 at 3:39 PM
marcoamendola wrote:

Since you are in a flow of modification in this area, how about defining a simple static property to hold the "." separator used to concatenate context?
This way we can easily customize the convention to get rid of the nested namespace - which "accidentally" I often do... :-) 

 


Done.

May 27, 2011 at 4:22 PM

That's a very nice improvement! Thanks for adding the separator, too :-)

Coordinator
May 28, 2011 at 8:34 PM

Uh oh. I updated the code and guess what...we probably break everybody's apps now ;) The reason is that this new mechanism is not handling namespaces at all. Some people prefer to organize things like this:

ViewModels.MyViewModel

Views.MyView

when running the new locator against ViewModels.MyViewModel it returns ViewModels.MyView instead of Views.MyView. That's a pretty big problem. I usually organize my system by feature, so it's probably not broken, but that's not true for everyone.

Can we look into this?

May 28, 2011 at 8:59 PM
Edited May 28, 2011 at 9:00 PM
EisenbergEffect wrote:

Uh oh. I updated the code and guess what...we probably break everybody's apps now ;) The reason is that this new mechanism is not handling namespaces at all. Some people prefer to organize things like this:

ViewModels.MyViewModel

Views.MyView

when running the new locator against ViewModels.MyViewModel it returns ViewModels.MyView instead of Views.MyView. That's a pretty big problem. I usually organize my system by feature, so it's probably not broken, but that's not true for everyone.

Can we look into this?

This should be a pretty easy fix, but what kind of assumptions do you want to make about the namespace for the ViewModel? Should we always assume it with be ViewModels.<Type> IF AND ONLY IF the View is of type Views.<ViewName>? Otherwise, you can add a custom convention in the bootstrapper to handle it. After all, that was the point of the change. 

Coordinator
May 28, 2011 at 11:18 PM

True. Except that I'm a RegEx fool :) We do need to make sure that we have the same behavior out of the box. There are basically two patterns that we supported for namespaces. One where everything was together, which should be already working, and one where views and view models were separated, in which case it was always ViewModels.Type => Views.Type.

So like this:

SomeNamespace.ViewModel => SomeNamespace.View

and

SomeNamespace.ViewModels.ViewModel => SomeNamespace.Views.View

May 28, 2011 at 11:26 PM
EisenbergEffect wrote:

True. Except that I'm a RegEx fool :) We do need to make sure that we have the same behavior out of the box. There are basically two patterns that we supported for namespaces. One where everything was together, which should be already working, and one where views and view models were separated, in which case it was always ViewModels.Type => Views.Type.

So like this:

SomeNamespace.ViewModel => SomeNamespace.View

and

SomeNamespace.ViewModels.ViewModel => SomeNamespace.Views.View


Gotcha. That's what I figured.

May 29, 2011 at 1:25 AM
Edited May 29, 2011 at 1:35 AM

I sent you a new pull request. Things got a little hairy with the regular expressions, but it required no changes to the existing transform mechanism. I'm pretty confident now that it can handle some really crazy stuff should we ever need it to. Originally, I thought it might get a little confusing to have both the GlobalFilterPattern and the ReplacePattern in the NameTransformConvention class since the default conventions in my previous changeset didn't use the GlobalFilterPattern. As it turns out, the feature was absolutely for adding support for namespaces. Anyway, I modified my test code (see below), and I think the results are what we want.

Func<string, string> funcVGetReplaceStr = (r) =>
{
    var repStr = ".DataContext";
    if (Regex.IsMatch(r, "Page$"))
    {
        return Regex.Replace(r, "Page$", repStr);
    }

    return Regex.Replace(r, "View$", repStr);
};

var vnamelist1 = String.Join(",", vmgr.GetResolvedNameList("MainPageViewModel").ToArray());
//MainPage

var vnamelist2 = String.Join(",", vmgr.GetResolvedNameList("ViewModels.CustomerViewModel").ToArray());
//Views.CustomerView

var cvnamelist1 = String.Join(",", vmgr.GetResolvedNameList("SomeNamespace.MainPageViewModel", funcVGetReplaceStr).ToArray());
//SomeNamespace.Main.DataContext

var cvnamelist2 = String.Join(",", vmgr.GetResolvedNameList("Some.Namespace.ViewModels.CustomerViewModel", funcVGetReplaceStr).ToArray());
//Some.Namespace.Views.Customer.DataContext

var vmmgr = ViewModelLocator.GetViewModelResolutionManager();

//Function for exclusion of interfaces (interfaces are included by default)
Func<string, string> funcVMGetReplaceStr = (r) =>
{

    if (Regex.IsMatch(r, @"I\${basename}")) //It's an interface transform so make it something impossible to exist
    {
        return String.Empty;
    }
    return r;
};

var vmnamelist1 = String.Join(",", vmmgr.GetResolvedNameList("MainPage").ToArray());
//MainPageViewModel,IMainPageViewModel

var vmnamelist2 = String.Join(",", vmmgr.GetResolvedNameList("Views.CustomerView").ToArray());
//ViewModels.CustomerViewModel,ViewModels.Customer,ViewModels.ICustomerViewModel,ViewModels.ICustomer

var ivmnamelist1 = String.Join(",", vmmgr.GetResolvedNameList("SomeNamespace.MainPage", funcVMGetReplaceStr).ToArray());
//SomeNamespace.MainPageViewModel,<blank>

var ivmmamelist2 = String.Join(",", vmmgr.GetResolvedNameList("Some.Namespace.Views.CustomerView", funcVMGetReplaceStr).ToArray());
//Some.Namespace.ViewModels.CustomerViewModel,Some.Namespace.ViewModels.Customer,<blank>,<blank>


Coordinator
May 29, 2011 at 2:56 AM

Those look pretty good. Thanks for looking into it. I'll probably do the merge some time tomorrow.

May 29, 2011 at 3:12 AM

What do you think of having a console application for running the test code above and allowing developers to test out their own conventions? I've been testing this code in the bootstrapper for one of the sample WP7 applications, but I've been having to blow out the changes when doing a pull from the trunk since it looks like this is an uncommitted change.

May 29, 2011 at 3:35 AM

Scratch that. A console app can't reference Silverlight assemblies. We'll need a simple Silverlight app to test it.

Coordinator
May 30, 2011 at 12:42 AM

I got the new RegEx fixes in. Thanks for taking care of that! Can I ask one more favor? Would you mind looking at the GameLibrary sample. In the bootstrapper it overrides the view model locator so that it can provide a custom mapping. I'm pretty sure that this can be handled by the new RegEx system without doing the override. Would you mind fixing that for me? After that I promise I'll go learn something about RegEx...I've been putting it off for as long as possible...looks like I have to learn it now :)

May 30, 2011 at 6:47 AM
EisenbergEffect wrote:

I got the new RegEx fixes in. Thanks for taking care of that! Can I ask one more favor? Would you mind looking at the GameLibrary sample. In the bootstrapper it overrides the view model locator so that it can provide a custom mapping. I'm pretty sure that this can be handled by the new RegEx system without doing the override. Would you mind fixing that for me? After that I promise I'll go learn something about RegEx...I've been putting it off for as long as possible...looks like I have to learn it now :)


I took a look at the code, but the custom convention seems to apply to only a single view in the entire application (GameDTO). That's the only one in which a View name is resolved by means of a Model instead of a ViewModel. Are you sure that you want this as part of the default conventions for ViewLocator?

That particular mapping convention is:

Namespace.Model.<BaseName> => Namespace.Views.<BaseName>

What we have currently as a default convention, when generalized, is:

Namespace.<SourceComponentTypePluralForm>.<BaseName><SourceComponentTypeSingularForm> => Namespace.Views.<BaseName>View

The differences are that Namespace.Model is not the plural form, there is no component type suffix after <BaseName> (which wouldn't make sense to do so semantically), and the View name doesn't end with "View".

I can certainly add the convention to resolve View names based on the Model names, but I think we should at least force the namespace to be called "Namespace.Models" and possibly require the View name to end with "View" for the sake of consistency. What do you think?

Coordinator
May 30, 2011 at 1:07 PM

No. I think you misunderstand. I don't want that as a default convention. I just want to add the transform rule to that one sample as an example of using the new API instead of having to override the whole function.

May 30, 2011 at 7:43 PM
EisenbergEffect wrote:

No. I think you misunderstand. I don't want that as a default convention. I just want to add the transform rule to that one sample as an example of using the new API instead of having to override the whole function.


You have a pull request. I don't know why this is happening but there are a bunch of old changesets in this latest pull request. Is there some way to "reset" this? I did do a local merge already. I don't know what's going on.

Coordinator
May 30, 2011 at 8:25 PM

Hmm. I'm not sure. I'll just copy the changed code in, since it's so small. BTW, did I mention that this is an awesome addition? Thanks!

May 30, 2011 at 9:41 PM

Glad I could contribute!

Coordinator
May 31, 2011 at 5:12 PM

Would you be willing to write a bit of documentation on the new API showing people how to add their own mapping conventions? That would be a great addition to the docs and help people in getting exactly the behavior they want.

Jun 1, 2011 at 3:29 PM
EisenbergEffect wrote:

Would you be willing to write a bit of documentation on the new API showing people how to add their own mapping conventions? That would be a great addition to the docs and help people in getting exactly the behavior they want.


If you do the general description of the classes involved and the method calls, I can do the documentation about the behaviors of the built-in rules and give examples of hypothetical custom scenarios. I don't want this to be a tutorial on regular expressions, but I can try to decipher how some of the built-in rules were constructed.

Coordinator
Jun 1, 2011 at 3:35 PM

Perhaps if you could just take one convention from the ViewLocator and it's corresponding convention from the ViewModelLocator and explain how they are used by the NameTransformer, that would be good enough. You would need to explain how each of the parameters from AddRule plays into the final transformations. I would take your description, augment it if necessary and add a new page to the docs for the content. I don't expect a details explanation of RegEx workings. That's definitely out of scope.