Παρουσίαση με Ετικέτες

Migrating a legacy real world application
15 Απριλίου 13 02:56 πμ | tolisss | 0 σχόλια   

Recently we made the decision to clone our Winforms VideoRent real world application and create a new XAF application – the XVideoRental. Wearing my LEGO designer hat Smile I will go through all migration steps as if I were in your shoes.

XVideoRental uses only a small part of XAF tooling –>Native modules + Code Central examples + open sourced project and community resources. All the time invested was for gathering ready to use implementations and putting them in a reusable project agnostic library. In addition since all these ready to use implementations exist already in our community project (eXpand) we created a second open source version of XVideoRental where this project agnostic library does not exist so we consumed even less resources for building it!

As you can read in the overview post the XVideoRental contains almost zero designed time code and everything is described declaratively in XAF’s Application Model xafml file, allowing full customization after distribution.

Real world applications are really demanding. We spend huge times for first release and in most cases is very poor compared to the next ones. The reason is simple, we do not have enough time to prepare a domain-specific language (DSL) that will bridge business requirements with our existing technical tooling/knowledge. Therefore we try to re-invent the wheel in many areas whereas XAF exists as the most comprehensive tooling available. Using application model and the Security System, XAF fully describes and configures the behavior of platform agnostic applications. Both Application Model and Security System are the technology abstraction or in other words the DSL language we need to minimize the time to market cost of a real world application.

We recommend:

1.  Watch the BUILDING A PROJECT MANAGER APPPLICATION IN 5 MIN video where we used the same LEGO designer approach as in XVideoRental in a simpler application as our MainDemo.



2.  Go for a quick overview of XVideoRental by reading XVideoRental real world application (RWA) – The overview.
3.  Go through the next table where from these simple statistics it should be clear the tremendous gain we get when developing with the XAF way.

  Number of projects Classes Lines of code
Legacy VideoRent
Location:
Four non reusable projects  256 27965
XAF XVideoRental • 1 project agnostic library
• 1 non reusable module
• 1 front end application almost unmodified as  created from VS templates
-
77
5
-
806
126
Open Sourced XVideoRental • References open sourced libs (project agnostic lib not exist)
• 1 non reusable module
• 1 front end application almost unmodified as  created from VS templates
-
36
5
-
807
126

In short the legacy app is using 256 classes. The XVideoRental much less 77 and 90% or them are simply concrete implementations from the referenced project agnostic library. However in the 3rd row where this project agnostic library is replaced from a reference to our open source project that number of classes goes further down to only 36!

Legacy app location:               %Public%\Documents\DXperience 12.2 Demos\Common\DevExpress.VideoRent.Win\CS\
XAF app location:                   %Public%\Documents\DXperience 12.2 Demos\eXpressApp Framework\XVideoRental\CS\
Open source XAF app location:
http://www.expandframework.com/downloads/download.html –>Demos\XVideoRental\

4.  Finally go through the list bellow where we compare the legacy and XAF application side by side.

Legacy VideoRent

XAF XVideoRental

Data Access  

• Legacy app uses ORM technology and our XPO to describe the video rent business. However special skills needed and extra efforts to create a clear separation from  other layers, so many helper classes exists even for very common tasks such as database connectivity.

• XAF has built-in support for both XPO and MS Entity Framework. We can simply utilize the legacy domain model by simply copy- paste the classes. Helper classes are of no use because XAF can handle all common tasks transparently for us!

• A real world application requires an importing mechanism for initial data. The legacy app imports data from xml files with structure that fits exactly to the structure of the business objects. Therefore even for a small  change in the BO design we need to modify and retest this mechanism.

• XVideoRental plugs-in an abstract domain agnostic importing engine from Fast prototyping requires an initial data import mechanism, allowing us to modify the structure of BO in the minimum time possible. In addition how to Supply Initial Data is well documented sparing our time for making architectural decisions.

• In a real world application sequential number integration is essential. However special design and knowledge is needed to be able to build something reliable.

• XVideoRental operates under a business application framework therefore a rich click and run SDK provides solutions to such common problems E2829. So  the developer only needs to integrate and not to think about the technical difficulties or guess the showstoppers.

Architecture  

Legacy app has a design time modularization based on Forms/UserControls/(Bussiness Concept). However it is not possible to extended it without adding new Forms and recompiling the whole application inside VS. In addition because of the lack in documentation determining the best place to write code for a specific behavior can still cause big headaches.

Application life cycle is component centric and was invented on demand for the current application.

XVideoRental demo is using XAF’s well-documented and simple to use MVC architecture. Also, while the discussed application is a simple fat client app, demanding users looking for something more advanced may also find a ready to use client-server solutions in XAF.

• VS templates to fast create modules. which by design are reusable and independent from main application.
• Well documented Application life cycle guide us where we to write code (e.g. Setup, Login, View Activation etc.)
• Simple to follow tutorial on how to Extend Functionality.
• Detailed guide of all the main concepts for building business applications.

Data Validation  

A real world application without strong validation support is unstable and has huge support times.
Building a validation engine is not trivial at all and requires third party components which will raise the cost even further. 
Therefore the legacy application time frame and budget wouldn’t allow any investment here and there is no validation support.

Creating validation rules does not require you to be a developer, even end-users can create them because it is quite easy and intuitive, not more difficult than creating a filtering rule in your Outlook. We only need to install the build-in Validation module!

Data Representation  

The legacy application a large number of components. Therefore the developer requires A huge amount of mundane, repetitive work was invested to:

XAF has native support for a large number of DX components. Automatic UI generation (CRUD detail and list forms, navigation and menu systems - all based on data models).  This is a huge time saver because almost every typical business application contains a good percentage of list and detail forms, navigation and menu systems - all linked together without any effort from your side.

• Create a large number of data entry forms, drag & drop numerous controls on it, arrange their positions and configure data bindings
• Providing a consistent look and feel is not an easy job and requires deep knowledge of a large number of components as well as a special design
• Interact with the database through XPO, create CRUD operations and support transactions needs careful considerations and a lot of time, so it was done as basic as possible by simply pushing non mandatory tasks such as undo operations and transaction for the next application release Smile.
• In an agile real world the navigation menu system should be controlled as declaratively as possible. However legacy app does not conform this requirement resulting in huge update times for every customer request.
• Extend XtraReports for every Business object we want to create reports.
• Design reports inside VS making their support  impossible in real world.
• Design analysis views inside VS making their support impossible in real world.

• We plugged-in a mechanism that allows to control any component at runtime from Dressing up our classes – Date with a model tonight!.
• A business rule driven Pivot editor borrowed from How to rule the Pivot we showed how to marry business requirements with a complex component like Pivot.
• Legacy code was converted on the spot to declarative as in Tooltips to the max - expressive UI.
• From Visiting dashboards we add a ready to use extension that provides collaboration for our views.
• We went over expectations by simply installing a community module from Dashboards in the real world – A Scotland strike.

Application Configuration  

Although most of the components can persist their state there is no application level integration by default. In addition their serialization is not designed to be human friendly and its hard to edit and support. The legacy developer had to create an integration mechanism deep in application’s infrastructure. This costly. wrap-up was as basic as possible and target only a few major forms producing a non consistent feeling.

XVideoRental is a XAF application which by design is described declaratively in XAF’s Application Model. Using Model Editor at runtime an end user can modify any part of the app.

However we didn’t spend the 10 min required to plugin the ModelDifference community module and consume the application from a persistence storage such as a database cause we were  building a clone and not demo the endless features of XAF!

Zero migration resources for this one!

Application Security  

The legacy developer tried to create a basic security implementation. However he soon realized that the efforts needed for something useful and reliable will probably exist the efforts for building the whole application. So, unfortunately due to app budget there is no investment in implementing a security system.

Our time frame here was really loosed since we already have a mature plug n’ play Security module. This flexibility allows us to plugin more goodies such as User Friendly permissions and  metadata based permission policies

Reporting  

The major goal of business applications is to be able to create and print reports.

Therefore the legacy app has a dedicated project for reporting. In which the developer had to use Visual Studio for report design. As a result he loosed any chance to update them on demand after project distribution which is a really common case.

At the same time the reports were extended and bound to VideoRent business objects making the whole implementation not reusable from any other project.

XVideoRental uses the built-in Reports Module which natively integrates our award winning XtraReports suite and provides a runtime designer.

The module saves the reports in the database so our job was to copy paste the Reports layout from the legacy app and distribute them as discussed in Distribute the Created Reports with the Application.

Moreover we provided collaboration/filtering with other views using as usual a no code approach as discussed in Visiting dashboards.

Data Printing and Export  

The legacy developer had to write special code for each control on your forms that he wished to print or export. Although this functionality is very useful in real world again the time frame wouldn’t allow such an investment.

XVideoRental can export data from the grid, pivot, chart, tree view, layout and others to a wide number of formats (PDF, RTF, TXT, CSV, HTML, MNT, XLS, XJSX, PNG, GIF, JPG, BMP, TIFF, WMF, EMF) without spending not even 1 minute to install or configure the system!

You probably can guess why eh? As usual XAF has a built-in generic mechanism for all controls out of the box!

Data Analysis  

Legacy app has a whole structure to support only a few data analysis views for the 4 major BO which are Customer, Movie, Receipt and Rent. Huge amount of code is located in dedicated forms for each analysis views making the solution not able to survive in real world. The reason of course is  that for each new customer request the developer has to change the code inside VS recompile and redistribute the app. A common example is a calculated value where it needs a UI to define these members, special algorithms to create them

XVideoRental uses the build-in Pivot Chart Module which as usual shifts development to the runtime allowing business users to modify the analysis display at any time. Uses the extended Pivot from How to rule the Pivot. Empowering the app with the dashboard suite as in Dashboards in the real world – A Scotland strike! was as simple as drag & drop the module from VS toolbox!. Essential for data analysis runtime calculated members as in Domain Components+ Calculated properties + Application Model was in the menu as well.

Localization  

There are technics for localizing .NET application via satellite assemblies however they do not localize application specific data and they are very time consuming, so the legacy app does not support any kind of localization

XAF supports all standard localization approaches and also addresses the problems that occur with them. With XAF, it is always possible to localize any part of your application at runtime (e.g., correct certain values from satellite assemblies). A convenient wizard provides the capability to use online translation services from MS, Google, etc. So, it is possible to leave the localization job to non-programmers who can easily import/export data without leaving the application.

Customizing Controls Appearance  

Even for the simplest operation like making bold a grid column or hiding a control from a view developer time is needed as long as recompilation and redistribution of the application

XVideoRental addresses this declaratively using the Conditional appearance module and the technic described in Dressing up our classes – Date with a model tonight! where any component can be serialized and controlled declaratively from XAF’s application model using the runtime Model editor.

This is control-agnostic and we spared our time digging into the specifics of each control – XAF did everything for us!

Implementing Custom Business Requirements  

Lets talk a concrete example here. The legacy app uses tooltips to create a more expressive UI. However even if the developer wrote a decoupled class at the end he has to attach it to various controls and forms. This makes the whole design not flexible since changes require developer presence.

XVideoRental can use the same decoupled class from the legacy application. However it simply attaches the behavior to application model instead of attaching it to controls and forms. This solution is project agnostic and allows later changes from a non programmer at runtime! This process is discussed in details in Tooltips to the max - expressive UI.

Getting Help and Support  

Application and developer are simply married. If for any reason they divorced then everything becomes very unstable and tricky. It is really hard to find another developer to continue support a legacy app. Even if we manage to do so the cost will be extremely high since there are no docs, support etc.

XVideoRental uses bricks/samples from XAF’s code central and community project. Thus by design there is a large number of developers that can support its code base. Not to forget the unmatched documentation and support we can get from the XAF team.

   

Conclusion

Even thought XAF does not contain solutions to each and every business problem in the world,  the framework is very strong in providing its own extensibility ( "preventing the lock-in effect").  It is fast and easy to plugin solutions to common business problems, at the end XAF is a Domain Specific Language that  that can bridge business requirements with our existing technical tooling/knowledge!

Until next time,

Happy XAF’ing!

Subscribe to XAF feed
Subscribe to community feed

Δημοσίευση στην κατηγορία: ,
How to rule the Pivot
16 Ιανουαρίου 13 07:25 πμ | tolisss | 0 σχόλια   

To configure our code we can simply use interfaces as parameters. XAF design is based on interfacesrefore it features amazing technologies like the Application Model and Domain Components which make available what no other framework offers (eg multiple inheritance, flexible design, no match in reusability, etc.). The Application Model for example describes all parts of a business application and can be further extended using interfaces. So, our code should simply query the values of these Application Model interfaces and operate accordingly. Let’s name these interfaces Rules and let’s try first to get a taste of existing implementations and then discuss a Pivot control ruling concept. Note here that instead of a Pivot it be any control, our goal is to describe behaviors in XAF’s Application Model, then implement them in a Controller and simply copy paste this controller to any project!

All the code needed for today’s discussion can be found in XVideoRental demo in Common.Win project under the NameSpaces: Common.Win.ModelAdapter, Common.Win.ColumnView.RepositoryItems, Common.Win.PivotGridControl.

Take a look at this ruling concept/idea in action in XAF’s Validation module. In the image bellow we see a set of interfaces that describe validation rules. The Validation Engine simply queries them and validates the objects accordingly.

image

Similar ruling based stuff can be found in our community project eXpandFrameWork, under a whole Logic Architecture concept. A few modules that use this architecture are AdditionalViewControls, ModelArtifact, MasterDetail, ConditionalDetailViews  The logic architecture is based in the composition over inheritance principle, meaning that it can make our rules amazingly powerful!. This is because we do not extend the IModelListView rather we add IModelListViews and other model artifacts to root model nodes like the ConditionalControllerState, LogicConditionalActionState we see in the image bellow.

 image

In this post however we will not dive so deep as our community project and we will concentrate to our XVideoRental demo. Take a look at this traditional windows form taken from the legacy VideoRent application of our Windows components suite.

image

The traditional developer needs to create a multidimensional UI given a collection of ChartPrice objects. One dimension is the type of the price (DVD,Blue-Ray,Video CD). Next one is the day number 1-7, third one is the different type in price double or integer for Default # of Rental Days. As you can see the traditional developer to implement this user interface used 3 tabs, 9x3 controls. Three of them must accept integers only and all other double numbers. This is an acceptable design however not flexible and here are a few reasons:

  1. The number of days is fixed, to add more days (eg. up to 10) more controls are needed.
  2. User interaction is needed from the end user, if he wants to see prices for Blue-Ray he must click on the assigned tab.
  3. The code that implements this works only for a certain windows form.

THE XAF WAY

XAF is a really smart framework, using it is inevitable that we will become equally smart cause we have unparalleled tools to work with. So, to create  a multidimensional UI we can simply use the PivotGridListEditor and create rules that we can use to describe what the traditional form does. Since we are talking about rules that will extend our Application Model we already start building an abstract mechanism that can be applied to any view and any object even at runtime with the help of Model Editor. However at this point let’s assign a PivotGridListEditor to the collection of ChartPrice objects to see the starting point and to have a comparing reference.

image

The PivotGridListEditor is perfect for multidimensional analysis thus our UI is already more flexible than the legacy one. However it is missing a lot of stuff (not editable,row header fromatting, cells formatting, object saving). We will discuss how to build all that stuff the XAF way and make them reusable to all of our projects!

Extending the Application Model to host different rule types

First lets create a collection of abstract rules and extend our Application Model’s IModelListView. To extend the Application Model we can follow this help document with make use of the bellow interfaces.

public interface IModelPivotRules : IModelNode, IModelList<IModelPivotRule> {

}

 

[ModelAbstractClass]

public interface IModelPivotRule : IModelNodeEnabled {

 

}

We choose to extend in a deeper level than IModelListView because we want to group the new Rules with the PivotGridListEditor option interfaces which are discussed in Dressing up our classes – Date with a model tonight!. So after extending the model the Model Editor for IModelListView will look like the following image.

imagetEd

Control the range of the cells

Next step is to design an interface that can help us to apply rules to certain Pivot control cells, so we need an interface with two properties Start, End

[ModelAbstractClass]

public interface IModelPivotSelectionRule : IModelPivotRule {

    Point Start { get; set; }

    Point End { get; set; }

}

No other action is required here, XAF’s TypesInfo system is already aware of IModelPivotSelectionRule since it derives from the already registered IModelPivotRule.

Formating the Pivot Cells

To format the cells of Pivot we need an Interface that:

a) Defines the range of the cells (eg. IModelPivotSelectionRule) .
b) Defines the PivotArea where the cells are located (Row, Column, Data).
c) Allows format configuration.

The interface bellow IModelFormatRule interface fulfills all the above requirements.

public interface IModelPivotArea : IModelNode {

    PivotArea PivotArea { get; set; }

}

public interface IModelFormatRule : IModelPivotArea, IModelFormatInfo, IModelPivotSelectionRule {

    [RuleValueComparison("IModelFormatRule_PivotArea_not_filter", DefaultContexts.Save, ValueComparisonType.NotEquals, PivotArea.FilterArea)]

    [DefaultValue(PivotArea.ColumnArea)]

    new PivotArea PivotArea { get; set; }

}

[ModelAbstractClass]

public interface IModelFormatInfo : IModelNode {

    string FormatString { get; set; }

    FormatType FormatType { get; set; }

}

Again no other action is required here, XAF’s TypesInfo system is already aware of IModelPivotSelectionRule since it derives from the already registered IModelPivotRule. In addition IModelFormatRule is not marked with  the ModelAbstractAttribute therefore the Model Editor will automatically add a menu entry as shown,

 image

Now we are ready to create a FormatRule for all row headers to display the info that the legacy windows form displays.

image

In the image we see that we created a FormatRule for RowArea cells that Start at X=0, Y=1 and End at the last cell X=-1, Y=-1. This rule will instruct a Controller to modify the initial ListView as shown bellow.

image

Next we will add one more FormatRule for the first row header.

image

What is different with this FormatRule  is the End X=0, Y=0 which points to the first row header and of course the FormatString. So, XAF first will evaluate first the “All row headers format” rule and then the “First Row Header” resulting in the following UI.

imageina

Finally we create a similar FormatRule for the second row header,

image

that will result in the following UI,

image

Using a declarative runtime approach we managed to format all row headers, XAF really teaches us amazing stuff!

Next let’s make PivotGridListEditor editable and we finished cloning the legacy functionality following an unbelievable flexible way – the XAF way!

All Pivot cells editable and double

We are now ready to start modeling the legacy windows form behavior. So, we need to make the Pivot cells editable therefore we first query our Support Center to see how this can be done –> E1232. From this example we understand that we can subscribe to certain events and replace the RepositoryItem of a Pivot cell. We already have a range of Pivot cells defined from the IModelPivotSelectionRule above and we are interested only in double and integer based Repositoryitems therefore an interface like bellow is sufficient.

[ModelDisplayName("SpinEdit")]

public interface IModelPivotSpinEditRule : IModelPivotSelectionRule {

    IModelRepositoryItemSpinEdit SpinEdit { get; }

}

 

The above interface derives from IModelPivotSelectionRule so it will provide a range of Pivot cells which their RepositoryItems will be replaced with a RepositoryItemSpinEdit (int, double). The IModelRepositoryItemSpinEdit is an interface that describes all properties of a RepositoryItemSpinEdit and can be created either by hand or automatically as discussed in Dressing up our classes – Date with a model tonight!

 

Let’s now create the first rule that will make all Pivot cells of the data area editable. Of course we need to write code to query this rule and also save this object as in E1232. However for the sake of simplicity as I already said in the beginning of this post all the code can be found in the Common.Win project of our XVideoRental demo. In this case look for the Common.Win.PivotGridControl.PivotGridController.

 

imageinstrcuts

 

In the image above: End X=-1, Y=-1 instructs our code to include all cells of the data area. Moreover since this is a RepositoryItem replacement rule it assumes that row and column headers are excluded so X=0, Y=0 point to the top left data cell.

 

With this rule the UI will be editable and accept double numbers as shown bellow,

 

image

 

Last rule will help us to format the edit value of the first row (Default # of Rental Days) to accept integers only as shown bellow, by simply setting the IsFloatValue to false.

 

 

image

 

More Rule Types

In XVideoRental we have more Rule types than the ones discussed in this post . It is rather easy to implement more and we would appreciate your ideas and contributions. So please feel free to use our Support Center to share them with the rest of our community. A list of the already implemented Pivot Rules is shown bellow. 

image

FieldToolTip rule

Tooltips are amazingly powerful and we already discussed them in depth at Tooltips to the max - expressive UI. However there I only posted a screenshot about pivot tooltips but I haven’t explained more since I needed more info that could make that post too hard to follow. Now we do have that extra info and I am talking about the IModelPivotSelectionRule interface which allows us to associate interfaces/rules/classes etc with a range of Pivot cells.

image

You can learn how to associate a class in this case the MovieToolTipController with an Application Model node at Tooltips to the max - expressive UI. under the TooltipController paragraph.

Try to imagine how expressive can a Pivot control become with different tooltips for different cells!

image

We will discuss the rest of the PivotRules (DrawCellRule, GroupIntervalRule, FieldSort) in a future post.

For now I want again to ask you all for your contributions/ideas regarding everything you see in our posts. Let’s use your real world experience and your XAF skills to improve our framework even more.

Controlling end user selection

As developers we should provide tools to our customers that can make their life easier. Let’s see what this means, PivotGridListEditor contains two components which are a PivotGridControl and a ChartControl hosted inside a LayoutControl. The ChartControl has as datasource the PivotGridControl so when the end user selects a range of cells the ChartControl automatically renders this selection as shown.

image

However when we close the view or the application the selection is lost and the end user has do it again. Moreover if we need to preconfigure a selection when the view opens we need to follow a repetitive way, that is search our Support Center for a similar sample eg select pivotgrid cells and then replicate something similar for all projects, views. I really do not like to spend my time doing repetitive tasks. It is much easier an faster to model it in the Application Model once at for all! To implement this we need an interface to extend the Application Model.

public interface IModelPivotGridSelection : IModelNode {

    Rectangle Rectangle { get; set; }

    [DefaultValue(true)]

    bool Synchronize { get; set; }

}

 

When Synchronise property is true the our code will write back the end user cell selection in the Rectangle property, when Synchronize is false we can use this functionality only for preconfiguring a cell selection when the view opens.

 

image

 

Moreover there are cases where we want to control the cell selection eg when a user selects a cell to auto select all cells in the row sparing his time, or disallow multiple column selection. I am sure it is pretty clear that all we need are a few more properties in the IModelPivotGridSelection interface to create amazing and reusable functionalities.

 

XVideoRental demo contains a really big number of Application Model Rules and I will probably need a large number of posts to talk about all of them. So I will concentrate in the more important ones. Feel free to explore the demo and shoot us with your questions and ideas!

 

As always happy XAFing with the smartest framework of all!

Δημοσίευση στην κατηγορία: , ,
Tooltips to the max - expressive UI
08 Ιανουαρίου 13 10:54 πμ | tolisss | 0 σχόλια   

UI simply depends on the smartness of our components. However the visible UI space is limited and most of the information is hidden behind components (tabs, popup forms etc). Therefore to display this hidden info user interaction is required. Tooltips however do not require any user interaction and our Suite supports tooltips with html formatting even in windows platform. We can already empower the detailed views of our XAF applications with native tooltip support as described in this help document. However when developing in XAF the sky’s the limit and in this post we will discuss ways to create tooltips as demoed in our XVideoRental RWA.

DataOnToolTip

By this we mean that we want to push any data a property of a business object has to a tooltip. Therefore, first we need to create a interface and extend our Application Model columns as described in our documentation,

[ModelAbstractClass]

public interface IModelColumnTooltipData : IModelColumn {

    IModelTooltipData TooltipData { get; }

}

public interface IModelTooltipData : IModelNode {

    [Category("DataOnToolTip")]

    bool DataOnToolTip { get; set; }

    [Category("DataOnToolTip")]

    int MaxHeight { get; set; }

    [Category("DataOnToolTip")]

    int MaxWidth { get; set; }

}

 

public class GridViewImageTextToolTipController : ViewController<ListView>, IModelExtender {

    public void ExtendModelInterfaces(ModelInterfaceExtenders extenders) {

        extenders.Add<IModelColumn, IModelColumnTooltipData>();

    }

The above will extend the Application Model as shown,

image

Next, we need to implement a method that when DataOnTooltip attribute is set will display the data in a tooltip like,

image

Of course due to the MVC XAF architecture it is really easy to reuse this functionality in any XAF project without not even one line of code!

ToolTipText

Now, how about a different case? Lets say that we have a complex Advanced Banded ListView and we want to guide end user to double click to a row area to see more info about the record. For this again we need to extend the Application Model with an attribute like,

    public interface IModelTooltipData : IModelNode {

        [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]

        string ToolTipText { get; set; }

//        ...

Then we can use the Model Editor to assign the text we want in the ToolTipText attribute and XAF will do the rest for us in any project!

image

ToolTipController

Extending the Application Model in order to be able to associate a class (controller) with any of its nodes can be done easily. First we add one more property to our IModelToolTipData interface like,

public interface IModelTooltipData : IModelNode {

    [DataSourceProperty("ToolTipControllers")]

    [TypeConverter(typeof(StringToTypeConverterBase))]

    Type ToolTipController { get; set; }

 

    [Browsable(false)]

    IEnumerable<Type> ToolTipControllers { get; }

The TypeConverter attribute will convert the type to a string so it will be possible for the Model Editor to show it and the DataSourceProperty attribute will populate the Types (Controllers) we want. What's left is to decide which classes will be in that list. This can be done be writing a Domain Logic for the non browsable ToolTipControllers enumeration like the following,

[DomainLogic(typeof(IModelTooltipData))]

public class IModelToolTipControllerDomainLogic  {

    public static IEnumerable<Type> Get_ToolTipControllers(IModelToolTipController modelToolTipController) {

        return FindTypeDescenants(typeof(ObjectToolTipController));

    }

    protected static IEnumerable<Type> FindTypeDescenants(Type type) {

        var typeInfo = XafTypesInfo.Instance.FindTypeInfo(type);

        return ReflectionHelper.FindTypeDescendants(typeInfo).Where(info => !info.IsAbstract).Select(info => info.Type);

    }

 

}

 

We have finished Application Model extension so let’s see how simple yet amazingly powerful is to write and apply such a controller for our Movie business object. So for a very simple ToolTipController like,

public class MovieToolTipController : ObjectToolTipController {

    const int MaxPhotoWidth = 120, MaxPhotoHeight = 120;

    public MovieToolTipController(Control parent) : base(parent) { }

 

    protected override void InitToolTipItem(ToolTipItem item) {

        var movie = ObjectSpace.FindObject<Movie>(CriteriaOperator.Parse("MovieTitle=?", EditObject));

        var photo = movie.Photo;

        if (photo != null)

            item.Image = photo.CreateImage(MaxPhotoWidth, MaxPhotoHeight);

        item.Text = GetMovieInfoHtml(movie);

    }

    public string GetMovieInfoHtml(Movie movie) {

        return string.Format("<b>{0}</b>\r\n<i>{2:D}</i>\r\r\n{1}", movie.Title, movie.Plot, movie.ReleaseDate);

    }

 

}

When assign it to a listview column,

image

XAF will popup an html formatted tooltip,

image

or we can use a similar approach for PivotGridListEditors

image

Everything discussed in this post exist in the Common.Win project under the Common.Win.General.ToolTip namespace of our XVideoRental demo.

Let us know if you have questions or subjects we want us to cover. Happy XAFing to everybody!

Δημοσίευση στην κατηγορία: , ,
ORM Magic–Importing from any datasource
29 Δεκεμβρίου 12 12:14 μμ | tolisss | 0 σχόλια   

This post will be on how to use the approach described in Fast prototyping requires an initial data import mechanism with Excel as input source. The technic is based on System.Data.DataSet class and can be applied to any type of input source!

Thanks to your reports and of course Slava’s help (XPO guru), XVideoRental importing mechanism has been improved a lot and now is faster, has notification events and is decoupled from XAF’s TypesInfo system. This makes it possible to simply copy the ImportData.cs file found in Common.Win project and use it in non XAF solutions!

In previous version this importing mechanism worked only when matching in types of input and output members. This means that if my output Oid property was a System.Guid then input should be of the same type. Now we have workaround this minor issue. If conversion is possible it will be done automatically without the need of any configuration or extra coding!

To better design, support, extend and describe the importing mechanism I used Mspec a functional testing framework and I open source the specifications in our community project eXpandFramework. These follow bellow,

MemberMapper, When Class Has a flag that includes all members
» should collect all members that belong to the class
» should not collect any base class member
» should create new members for each one of them

MemberMapper, When class does not have a flag that includes all ownmembers
» should not create members for those not marked with the attribute
» should create members and name them according to the attribute data
» should create a key property if not included in the conficuration

MemberMapper, When class attribute has data for base members
» should create and name them according to the attribute data
» should map their attributes

MemberMapper, When class is marked to include all member but member is marked seperately
» should use the member marking

MemberMapper, When mapping a referenced member
» should create a member with a dynamic type ownwer

MemberMapper, When reference type is not includedIN the configuration
» should create non reference member

ClassMapper, When creating dynamic classes
» should Create Classes only for the ones that have a marking attribute
» should name the classes taking data from marking attribute

ClassMapper, When class has many to many collection marked for importing
» should create intermediate classes
» should create an auto genareted key for this class
» should create 2 columns with names taken from the marked attribute

DictionaryMapper, When is mapping a dictionary
» should map all marked objects

InitDataImporter, When importing an object
» should create a new output object
» should assign all mapped properties

InitDataImporter, When input membertype is different than output
» should convert the value when simple type
» should convert the value when reference type


21 passed, 0 failed, 0 skipped, took 1.61 seconds (Machine.Specifications 0.5.2-98b543c).

The above specifications are evaluated with every eXpand build and you can see them in eXpand’s build server. Take a quick look at their code located in github to see how easy it is to write them (http://goo.gl/TNv4d).

Now lets see how to use our magic XPO ORM to import into the real world business domain like the one of our XVideoRental demo,

image

 

For the sake of complexity the input source will be a list of excel files and not just a simple Excel file with many sheets.

image

XPO supports a DataStore provider which is based on DataSet. So, first we fill a DataSet with the excel files and for this I will use some DataSet extension methods I contributed to eXpand (see http://goo.gl/TF26g)

static DataSet DataSet() {

    var dataSet = new DataSet();

 

    dataSet.ImportExcelXLS(new[]{

        "Customer", "Receipt", "Company", "CompanyType", "Country", "Employee", "Language", "Movie", "MovieArtist",

        "MovieArtistLine", "MovieCategory", "MovieCategoryPrice", "MovieCompany", "MovieItem",

        "MovieMovies_CountryCountries", "MoviePicture","Person","Artist","ArtistPicture","Rent"

    });

 

    return dataSet;

}

 

Now we are ready to create a UnitOfWork with this DataSet as DataStore like,

 

var inputUnitOfWork = new UnitOfWork(new SimpleDataLayer(new DataSetDataStore(DataSet(), AutoCreateOption.None)));

 

and finally call the Import method of the InitDataImporter class as shown bellow

 

var initDataImporter = new InitDataImporter();

            var unitOfWork = OutputUnitOfWork();

            var inputUnitOfWork = new UnitOfWork(new SimpleDataLayer(new DataSetDataStore(DataSet(), AutoCreateOption.None)));

            initDataImporter.Import(() => new UnitOfWork(unitOfWork.ObjectLayer), () => new UnitOfWork(inputUnitOfWork.ObjectLayer));

This simple, however powerful technic can be applied to any type of input source as long as you are able to fill a DataSet!

You can download a sample project was created with v12.2.5 of our Suite from Importer.Console.

Happy New Year to everybody!

Δημοσίευση στην κατηγορία: ,
XVideoRental real world application (RWA) – The overview
18 Δεκεμβρίου 12 04:29 μμ | tolisss | 0 σχόλια   

XAF knowledge base is really rich and in our Support Center you can find solutions for all common business problems. Moreover our community project www.expandframework.com has tones of reusable solutions, we collected a few of them and applied them to the video rent business. The demo is available with 12.2.4 version of our Suite and can be found in the same folder with the other amazing XAF demos!

XAF is a framework that provides the tools that a developer needs for building business solutions.

  1. A state of the art multi layered configuration system – The Application Model.
  2. A robust and flexible Security System that can be used to protect our data and control the auto generation of the UI based on Role permissions
  3. Its own reflection system (TypesInfo)– with amazingly simple ways to do what .NET does not offer eg. Runtime members, dynamic attributes etc.
  4. A well designed architecture to guide you where you should put your code. Moreover a very flexible modularization for structuring and further supporting any solution.
  5. WinForms/ASP.NET integration for a large number of our components
  6. Rich documentation and a click and run SDK!

XVideoRental is a real world application (RWA). It is designed as a clone of our WinForms VideoRent application and demos only a small part of XAF capabilities. XAF provides the tools/architecture to do extraordinary things so we have followed a (no code)/(design at runtime) approach!. We recommend you to open the legacy Winforms demo and XVideoRental side by side and compare how much faster and richer is XAF development versus the traditional one. Moreover take a look at this help document that extensively compares traditional vs XAF development.

  1. XVideoRental uses a mechanism to serialize classes into Application Model and control them further from there! Therefore minimizes the learning curve since it is based on your existing component knowledge. (see this blog)
  2. It is a modeling rather than development technic. In addition allows further modeling at runtime since XAF already provides a runtime model editor.
  3. Implementations are collected from our usual places (Support Center / Code Central) / www.expandframework.com.

The XVideoRental demo has three projects:

Common.Win

This is a library (not XAF module) and contains 95% of the code needed to model the VideoRental business! As a library can be reused from all domains and not only for video rental business. By extending the model as discussed in Dressing up our classes – Date with a model tonight! it is possible to create an abstract mechanism and control any class/component from there. Since all business operations can be modeled, the library contains controllers like NetIncomeController, TopObjectController that map to the real world meanings and can be applied to any domain. The XAF Application Model serves as an abstraction from technology and business specifics. This module is assembled by collecting the classes/implementations from our Support Center and from our community project www.expandframework.com.

XVideoRental.Module.Win

References Common.Win library and simple initializes the required classes/controllers by deriving from the abstract implementation of Common.Win library. However even if it is possible to “model” any behavior sometimes technical depth must be considered. Therefore in the project you will find a small number of video rental specific classes. In this project you can also find the model differences for this business domain.

XVideoRental.Win

This is the application project and contains no code. Only a few default configurations like module and security registrations.

In the next post we are going to discuss the steps involved in building this application. I remind you again that all code functionality is borrowed from our community, this means that code / ideas really belong to you! We welcome more of your contributions and ideas to build even more wonderful applications. Please explore this demo and we are waiting for your feedback in order to blog more about features that interest you.

A similar version can found in our community project www.expandframework.com. This version has exactly the same functionality as the original demo. However it references directly the eXpand framework so the Common.Win project does not exist nor the initialization of the controllers in the XVideoRental.Module.Win.

We are looking forward for your feedback and contributions in order to make this demo even more powerful! In its current state, a developer can replace before lunch all the business objects with objects of a different business domain then package the application and go to customer and continue development there, at runtime! The final goal as developers is to build such configurable applications that business users can use and modify and shift this weight of our backs. XAF provides all the tools for this and this demo is a proof for this!

Bellow is a short video that shows this demo. You can find about two more dozen of images of this demo in our FB group

PS: A thanks to everybody that already provided feedback and reported issues with this demo. We already provided a newer version with improved performance and you can find it here. For posts related to the XVideoRental demo please subscribe to to the XVideoRental tag

Happy XAFing!

Δημοσίευση στην κατηγορία: ,
Dressing up our classes – Date with a model tonight!
03 Δεκεμβρίου 12 10:40 πμ | tolisss | 0 σχόλια   

Classes are in a sense behavior libraries. To initialize or configure them, we can use their properties. Serialization is a technic that helps distribute the state of our classes. In this post we will discuss how to serialize any class in the multi-layer XAF model! Then we finish with the model synchronizers which will control the class. Having a class or a part of a class serialized in the model makes it possible to continue development there without writing more code (declarative/runtime approach).

Runtime classes

In .NET is super easy to create runtime classes or interfaces. The following snippet will create a assembly with a Dynamic class.

var provider = CodeDomProvider.CreateProvider("c#");

var results = provider.CompileAssemblyFromSource(new CompilerParameters(), new[] { @"public class DynamicClass{}"        });

Assembly compiledAssembly = results.CompiledAssembly;

Modeling

XAF’s super advanced and simple model technology is using interfaces for design and further extension. This is well documented How to: Extend Application Model. To serialize any class on the XAF model we simply need to use reflection, extract an interface from the class and extend any part of the model we want with it.

Let’s see a few examples using XAF build-in components.

1) GridListEditor

XAF’s GridListEditor is based on the GridView class which is a very sophisticated component with a lot of properties. Serializing it into the model allow us to control it from there. Using the model it is possible to work at runtime and since we have a lot of properties it is wise to serialize their help as well (see red arrow).

image

2) ChartListEditor

This is a very useful editor that also needs better control from our model. Note that this model serialization is reusable from all our projects!

image

This technic can boost our runtime experience and make it possible to work side by side with our customer building really fast. Furthermore it is applicable to any class or component. Let’s a few more interesting examples.

3) Repository Items

XAF’s DX PropertyEditors render DX controls which store their configuration in RepositoryItem classes. We can serialize all ReporitoryItem descendants and extend the IModelColumn. As a result by simply changing a model attribute we can do things at runtime that with a code approach would be very time consuming.

image

4) The SchedulerListEditor

image

5) The PivotListEditor

This one uses the same serialization approach however since this is a very useful editor we modeled a few extra behaviors – the pivot rules!. We would probably create a separate post about them.

image

Furthermore here we need to notice that we can model business meanings such as NetIncome, so for the following model modifications,

image

XAF will render the View bellow without any coding or dependency to any object!

image

Another example, when we talk about the TopObject meaning, we can model it like

image

and XAF will give us the following View again without writing not even one line of code (no code==no bugs)

image

Model synchronization

ModelSynchronizers can be used to:

a) set up an entity according to the configuration stored in the Application Model
b) Persists the configuration of an entity into the Application Model

Model’s nature makes it very abstract so since the attributes of the model are automatically generated from the properties of a class, its rather easy to do the opposite. Therefore we can write an abstract class that will implement IModelSynchronizable interface. The method SynchronizeValues is reading from any class and updates the model. The method ApplyValues is reading the values of the model and synchronize any class that properties match model’s attribute Ids.

protected void SynchronizeValues(ModelNode modelNode, object component, PropertyDescriptorCollection properties) {

    foreach (var valueInfo in GetModelValueInfos(modelNode)) {

        var propertyDescriptor = properties.Find(valueInfo.Name, false);

        if (propertyDescriptor != null) {

            var propertyValue = GetPropertyValue(component, propertyDescriptor, valueInfo, modelNode);

            var modelValue = GetSynchronizeValuesNodeValue(modelNode, valueInfo, propertyDescriptor, valueInfo.PropertyType.IsNullableType(), component);

            if (modelValue != null && !modelValue.Equals(propertyValue)) {

                modelNode.SetValue(valueInfo.Name, propertyValue);

            }

        }

    }

}

 

protected void ApplyValues(ModelNode node, object component, PropertyDescriptorCollection properties) {

    foreach (var valueInfo in GetModelValueInfos(node)) {

        var propertyDescriptor = properties.Find(valueInfo.Name, false);

        if (propertyDescriptor != null) {

            var nodeValue = GetApplyModelNodeValue(node, valueInfo);

            if (nodeValue != null) {

                var propertyType = propertyDescriptor.PropertyType;

                var propertyValue = propertyDescriptor.GetValue(component);

                if ((!IsDefaultCoreValue(nodeValue, propertyType) || (!nodeValue.Equals(propertyValue))) && propertyType.IsValidEnum(nodeValue)) {

                    if (!nodeValue.Equals(propertyValue))

                        propertyDescriptor.SetValue(component, nodeValue);

                }

            }

        }

    }

}

 

Finally for each component we want to synchronize we create a descendant of the above implementation. For example,

AdvBandedListEditor

public class AdvBandedViewOptionsSynchronizer : ComponentSynchronizer<DevExpress.XtraGrid.Views.BandedGrid.AdvBandedGridView, IModelOptionsAdvBandedView> {

    public AdvBandedViewOptionsSynchronizer(AdvBandedListEditor control)

        : base(control.GridView, control.Model.OptionsAdvBandedView, ((IColumnViewEditor)control).OverrideViewDesignMode) {

    }

}

 

ChartControlListEditor

public class ChartControlSynchronizer : ComponentSynchronizer<DevExpress.XtraCharts.ChartControl, IModelOptionsChart> {

    readonly XafApplication _application;

 

We have discussed ways to model components into a distributable layer that describes a XAF. Even more we show how simple would be a model representation of business meanings (eg. NetIncome). It is clear that these tools are reusable from any project. We only need to feed XAF with a business domain and a few model modifications even in runtime to be able to have a working solution! A solution so rich in features that it is impossible to implement using the traditional approach.

The code and screen shots are taken from the XVideoRental application. This demo that can be found along with the other XAF demos in v12.2. Next posts will be about this new demo that really proves how XAF can save our time by lifting the development to the runtime!

P.S. If you are a facebook fun you can support us with a like for our new XAF page.

We are happy to read your feedback about this!. Remember that your questions are the best candidates for future posts.

Happy XAFing!


Δημοσίευση στην κατηγορία: ,

Search

Go

Το Ιστολόγιο

Ιστορικό Δημοσιεύσεων

Συνδρομές