Saturday, August 20, 2011

VS 2010 Setup Project - how to upgrade?


Setup projects under VS2005 and VS2008 were easy to upgrade:
  1. select the Setup project
  2. go to the Properties tab
  3. update the Setup project Version
  4. accept VS suggestion to change the Product Code
  5. build the Setup project
This isn't enough under VS2010.
Is it a bug? In fact no. It happens that VS2010 uses the installer in a smarter way. The MSI generated by VS2010 only replaces changed assemblies. The same principle is used by ClickOnce and it makes upgrades faster.

The question is: what is a changed assembly? Different update date? Different size? Not at all. Assemblies are different when they have a different File Version. As simple as that.
I'm not sure ClickOnce uses this criteria to identify different assemblies.

Upgrading a Setup project under VS2010 is a bit more complicated:
  1. update the File Version of all assemblies that are changed for this upgrade
  2. generate new binaries for these assemblies
  3. select the Setup project
  4. go to the Properties tab
  5. update the Setup project Version
  6. accept VS suggestion to change the Product Code
  7. build the Setup project
To know more about this subject and understand why you need to do it this way under VS2010, you can read an interesting discussion.

So what about the SolutionInfo and the Consistent Version Numbers Across All Assemblies technique? It's a way to make sure you don't forget to update the File Version of all assemblies, even if they didn't change. It's a kind'a "fail safe" upgrade. Of course you risk to replace too many assemblies that in fact didn't need to be replaced. The choice is yours.

Sunday, July 31, 2011

How "dynamic" made my life easier


Some coworker said once "Every time you hear dynamic means a load of troubles is coming by". I didn't agree. I know lots of interesting stuff can only be done using Reflection and even Reflection.Emit. Just to give some context, you are talking about Microsoft Framework 4.0 and the new type dynamic type declaration.

As you know C# is a statically typed language. As you also know, this means you must declare the type of every variable, field or property, before you can use it. The var keyword didn't change that rule a bit. Using var you are implicitly declaring tha variable type. The compiler knows the correct type of  var and the keyword is replaced by the correct type at compile time.

Let's rephrase: the type of each variable, field or property must be known at compile time. Then Framework 4.0 and _Dynamic Language Runtime_ brought us dynamic. We must change the definition above as the real type dynamic is unknown at compile time. A dynamic type can be any type at all so it's legal to do any operation you like with it. The compiler won't complain about it being incorrect as it doesn't know the real type.

You can argue that System.Object could do the the trick but you also know the range of operations you can do with System.Object is very narrow and you have to cast it to another type in order to get the same kind of usability, I mean in order to support all operations other types support. No more limitations like that:
  • declare a variable as dynamic
  • your first assignmenet to this variable defines the real type it will have
  • the legal or illegal operations will be evaluated after this assignement
What's the catch? Incompatibilities that couldn't show on compile time will show at runtime. So if you practice "jerk programming", you will get "a load of troubles" and my coworker's statement will prove correct.

What do I need dynamic for?
The classical problem is the "custom properties" issue. You have an business application but every customer wants its own set of extra properties and the requirements of the customer can overcome your worst scenarios/nighmares. You could go the Reflection.Emit way but that's really hard for most programers. Let's try the dynamic way.

Define you CustomPropery class like this:

using System;

public class CustomProperty
{
    #region Private Fields

    private string _name = String.Empty;
    private string _type = String.Empty;
    private dynamic _value;

    #endregion

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public string Type
    {
        get { return _type; }
        set { _type = value; }
    }

    public dynamic Value
    {
        get { return _value; }
        set { _value = value; }
    }
}


Notice dynamic is used both on the field and on the property.
I suppose you will now read the CustomProperty definitions from some storage be it a database, XML file, it really does't matter.

Now you need a method that converts the type that you read as a String into a Type.

private static Type GetDataType(string type)
{
    Type propType = Type.GetType(type);
    if (propType == null)
        propType = Type.GetType("System." + type);
    if (propType == null)
        propType = Type.GetType("App.CustomProperties." + type);

    return propType;
}


Just to put it all together, after reading the definitions to a prop of PropertyInfo type, you assign the real type like this:

var customProperty = new CustomProperty();
customProperty.Name = prop.Name;
customProperty.Type = prop.PropertyType.Name;

Type targetType = GetDataType(customProperty.Type);
if (targetType != null)
{
    if (targetType.IsEnum)
        customProperty.Value = ConvertStringToEnum(targetType, "");
    else if (targetType == typeof (Int16))
        customProperty.Value = (Int16) 0;
    else if (targetType == typeof (Int32))
        customProperty.Value = (Int32) 0;
    else if (targetType == typeof (Int64))
        customProperty.Value = (Int64) 0;
}
else
{
    customProperty.Value = " ";
    customProperty.Value = string.Empty;
}


After the first assignement juts to define the real Type,  you can now take care of assigning the real value, knowing it will have the correct Type.

In this example I need the properties for use in a PropertyGrid. In each grid row, I show the customProperty.Name followed by the customProperty.Value. The sample presented here is very limited in scope and isn't really a How To. The point is:
  1. there is no keyword to define the real type of a dynamic variable/field/property
  2. the real type is defined by the first assignement
  3. do this assignment as soon as you know the real type
  4. assign the actual value after the previous assignment

Sunday, July 10, 2011

You can't serialize Dictionary


Too bad:)
I have to make a class MyDictionary with two field, key and value, both beeing strings. Then maybe I can serialize a List.
Then again, this guy has a Solution!


Friday, May 20, 2011

Caliburn.Micro and CSLA framework


What's better than one framework? Two frameworks!

Back in February I merged Csla.Xaml.ViewModel with Caliburn.Micro.Screen class and the result was a new ScreenWithModelBase class added to my version of Caliburn.Micro.

This Caliburn.Micro extension for CSLA.NET makes life easier for those who want to use both frameworks and makes Caliburn.Micro a very interesting alternative to the BXF framework that is so popular on the CSLA world (as Rocky uses it on all Silverlight project samples).

Yesterday an old announcement on CSLA.NET forum received some attention and Jonny Bekkum asked me whether he could add this class to CslaContrib project. That was done a while ago.

Sunday, April 24, 2011

Technical Note: Silverlight code for CSLA 4



This note was written for CslaGenFork project.

Summary
When using a Silverlight client, your application must always use an application server. Because of Silverligt restrictions, the business objects library DLL must be different on the Silverlight client and on the application server. In this post we will see what are those restrictions, the solutions to the issues they raise and how to use the generated code. In fact this post summarizes what needs to be changed in order to run CSLA code under Silverlight.

N.B. - CSLA Silverlight changes are numbered and marked in bold.


I - Silverlight restrictions

Due to security reasons, there are a lot of things you can't do on Silverlight code. For what CSLA cares, there are three things you can't do under Silverlight:
1. Access a database server, namely SQL Server
2. Make synchronous calls to the application server
3. Use reflection on non-public members of other classes (one class can't use reflection on private members of another class)
Let's analyse the CSLA solutions for each one of these restrictions.


II - CSLA solutions

1. The Silverlight client must receive and send the data through the application server.

CSLA.NET automatically takes care of routing all DataPortal calls to the application server. If CSLA.NET doesn't find a suitable DataPortal method in the client code, it routes the call to the application server.

1.1. DataPortal_Create is a special case because most of the times you want it to run locally.
Regular CSLA uses the attribute [RunLocal] to mark DataPortal methods that must be run on the client (client side DataPortal concept). When DataPortal_Create exists, it's a strong candidate to run client side unless you need to load object default values from the database.
On Silverlight, DataPortal client side methods accept an extra parameter DataPortal.ProxyModes.LocalOnly that forces the DataPortal code to run locally.

1.1.1. On the Silverlight client, to run DataPortal_Create locally, there must be a specific asynchronous DataPortal_Create method.
The Silverlight signature is different from the equivalent method that may exist on non-Silverlight clients.
The Silverlight signature looks like this:
public override void DataPortal_Create(Csla.DataPortalClient.LocalProxy.CompletedHandler handler)
The regular CSLA signature looks like this:
protected override void DataPortal_Create()

1.1.2. On the Silverlight client, there must be a specific asynchronous factory method that invokes DataPortal.BeginCreate passing that extra parameter.
The Silverlight invocation looks like this:
DataPortal.BeginCreate(callback, DataPortal.ProxyModes.LocalOnly);
The regular CSLA asynchronous invocation looks like this:
DataPortal.BeginCreate(callback);

N.B. - All DataPortal_XYZ methods can run locally. This might be useful in scenarios where the Silverlight client is using REST or SOAP services to interact with the database.

2. The Silverlight client must invoke the application server asynchronously.
CslaGenFork can generate synchronous or asynchronous code. When generating Silverlight, asynchronous code is always generated. This includes:

2.1. Asynchronous LazyLoad for properties (may be synchronous or asynchronous under regular CSLA, but never both at the same time).
If both options for synchronous and asynchronous code generation are set, under Silverlight the getter code will be asynchronous code and synchronous code for non-Silverlight environments.

2.2. Asynchronous Factory methods (may be both synchronous and asynchronous under regular CSLA).
The Silverlight and synchronous factory methods are called asynchronously and they invoke the DataPortal methods asynchronously. CGF generates synchronous and asynchronous code according to the settings (no conditions here).

N.B. - Business rules that must get data from the application server must also run asynchronously. That's a problem that must be addressed by the rule developer but beyond CslaGenFork concerns.

3. On the Silverlight client, all usual private or protected member must be public.
This issue is solved with code like this:
#if SILVERLIGHT
    [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
    public ...
#else
    private ...
#endif
The EditorBrowsable attribute intends to hide the member from InteliSense (and from the developer) as a way not to encourage its use.
This issue shows on the following cases:

3.1. public PropertyInfo declaration (private under regular CSLA)

3.2. public class constructor (private under regular CSLA)

3.3. public AddObjectAuthorizationRules (protected under regular CSLA)

3.4. public DataPortal methods (some are private or protected under regular CSLA)


III - What is generated and how to use it

As of November 2011, CslaGenFork generates both Encapsulated Implementation and Encapsulated Invoke DataPortal models (according to Using Csla 4 ebooks classification). The usual 2 files are generated: the .Designer file and the extended file.
The extended file is where CGF puts the commented partial method implementation of the Pseudo Event Handlers. Note that all these methods run server side. If you are regenerating a project, you should put a pair of conditional compilation directives around the whole region:
#if !SILVERLIGHT
#endif
In the .Designer file you will also find a lot of directives just like the above. According to the compilation symbols defined in your project, some parts of the code are ignored. This way you take the same source code and get two different DLLs: one for the Silverlight client and another for the application server. The later can also be used on:
  • WPF client application
  • WPF application server
  • ASP.NET application server
N.B. - For Windows Forms there are other issues (ListBase versus BindingListBase inheritance) that prevent the use of the same DLL.

One way to accomplish this goal is to make a copy of all source files and put each copy in a different project: one on a Silverlight Class Library project and another on a Windows Class Library project.

A more usual approach does the same thing except you don't copy the files but use kind'a shortcuts. Say your main project is the Windows Class Library. Put the files there and build it as usual. On the Silverlight Class Library project, add all folders needed by the project. After that, go to each of the folders and add existing items. Now that's the magic part: navigate to your main project files, select the files and instead of clicking Add, click the small down arrow and click Add As Link.

Tiago Freitas Leal

Links:
CSLA.NET
CslaGenFork

Monday, March 14, 2011

Injecting a logger in Caliburn.Micro



CM defines a ILog interface. The LogManager class implements a NullLog. It's CM default implementation. As it is, it's not very useful. I looked around and found How To Do Logging with Caliburn.Micro. It works all right on my WPF project. The question now is I don't want to specify my logger in code, I want to use DI/IoC pattern (Dependency Injection/Inversion of Control). This means I want to specify the logger in my App.config. Sounds easy, been there, done that.

1) Create a project Logger.
2) Add a reference to the Caliburn.Micro assembly you are using (be it WPF, Silverlight or WP7).
3) Add references to NLog and log4net and whatever logging library you might want to use. I'm using NLog 1.0 Refresh and it works all right.
4) Copy the ILog implementations from How To Do Logging with Caliburn.Micro to this project.
5) Change the namespace of the classes to Logger and make the classes scope public.
6) Build the Logger project just to make sure everything is ok.
7) Go back to your main project and remove all references to NLog, log4net, etc.
8) On your main project open App.config and a add a line in the appSettings section:
<add key="Logger" value="Logger.NLogLogger, Logger" />

Now we need a method to inject the class as our logger.

9) On your main application, add a class like this:

using System;
using System.Configuration;
using Caliburn.Micro;

namespace CaliburnMicroWpfApp.Framework
{
    /// <summary>

    /// Manages the injection of the logger.
    /// </summary>
    public static class LoggerFactory
    {

        /// <summary>
        /// Creates logger instance.
        /// </summary>
        /// <returns>The ILog instance.</returns>
        public static ILog GetLogger(Type type)
        {
            Type loggerType;

            var loggerTypeName = ConfigurationManager.AppSettings["Logger"];
            if (!string.IsNullOrEmpty(loggerTypeName))
                loggerType = Type.GetType(loggerTypeName);
            else
                throw new NullReferenceException("Logger");

            if (loggerType == null)
                throw new ArgumentException(string.Format("Type {0} could not be found", loggerTypeName));

            return (ILog)Activator.CreateInstance(loggerType, type);
        }
    }
}


10) Call the GetLogger method in your bootstrapper class. Mine is like this:

using Caliburn.Micro;
using CaliburnMicroWpfApp.Framework;
using CaliburnMicroWpfApp.ViewModels;

namespace CaliburnMicroWpfApp
{
    public class DefaultBootstrapper : Bootstrapper
    {
        static DefaultBootstrapper()
        {
            LogManager.GetLog = type => LoggerFactory.GetLogger(type);
        }
    }
}


11) Don't forget to add a nlog section to your App.config or a NLog.config file.

That's it.

Saturday, February 12, 2011

Caliburn.Micro WindowsManager.Show_XYZ methods



While Rob Eisenberg is writing The Window Manager I might as well share my findings about it.

There are 3 Show_XYZ methods:


  • ShowDialog() - shows a modal window
  • ShowWindow() - shows a modeless window
  • ShowPopup() - shows a popup
For ShowDialog() and ShowWindow(), your view should be a Window. If your view is a UserControl behind the scene Caliburn.Micro will create a window to host it. You call the method like this:

public void ShowModal()
{
    var wm = new WindowManager();
    var vm = new ModalViewModel();
    wm.ShowDialog(vm);
}

public void ShowWindow()
{
    var wm = new WindowManager();
    var vm = new WindowViewModel();
    wm.ShowWindow(vm);
}


I found ShowPopup() a bit less intuitive to use. Your view must be a UserControl and not a Popup as you might expect.

public void ShowPopup()
{
    var wm = new WindowManager();
    var vm = new PopupViewModel();
    var settings = new Dictionary();
    settings.Add("StaysOpen", false);
    wm.ShowPopup(vm, null, settings);
}


That's it. happy coding!


UPDATE - You can find a detailed artcle on WindowManager at Caliburn Micro Part 5: The Window Manager.