Tuesday, August 17, 2010

On Demand Loading of Assembly in Silverlight

Hi guys I am posting a new article on, on demand loading of assembly in Silverlight applications. Nowadays when you develop application in Silverlight you may not need to load the entire assembly into client side. Instead of that you can download whenever it needs in your application by separating it into separate XAP or DLL files. By doing this the initial downloading size of XAP can be reduced and finally improvement in initial loading of your application. Another very nice feature of this approach is you can invoke function of other DLL or XAP files. Even your can set/get value of property belong to that assembly. In Silverlight this feature is very useful because the library has to be downloaded in to the client machine before start executing.

In this section I am going to explore following things:

1. Reflection (One amazing feature)

2. Downloading Library using Web client

3. Assembly

4. Get all types from assembly

Here I am trying to load a user control one XAP file to another container XAP file. For this I have two Silverlight projects.

1. Controlapp (target user control)

2. Slvdynamicloadingreflection (container application)

Here is the implementation of target user control;

Lets create two folders

1. Model

2. ViewModel

The Model will be having the model class, Following is the code for my model class;

public class Person : INotifyPropertyChanged
{
    private string _FirstName;
    public string FirstName
    {
        get
        {
            return _FirstName;
        }
        set
        {
            _FirstName = value;
            NotifyPropertyChanged("FirstName");
        }
    }
    private string _LastName;
    public string LastName
    {
        get
        {
            return _LastName;
        }
        set
        {
            _LastName = value;
            NotifyPropertyChanged("LastName");
        }
    }
    #region INotifyPropertyChanged Members
 
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    #endregion
}

In above code snippet I have a class called Person with two properties FirstName and LastName, basic person information;


Once you created the model lets create the ViewModelPerson.cs




public class ViewModelPerson : INotifyPropertyChanged
{
    private Person _Person;
    public Person Person
    {
        get
        {
            return _Person;
        }
        set
        {
            _Person = value;
            NotifyPropertyChanged("Person");
        }
    }
    public ViewModelPerson()
    {
        Person = new Person
        {
            FirstName = "",
            LastName = ""
        };
    }
 
    public void Save()
    {
        MessageBox.Show("Method Invoked");
    }
 
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
    #endregion
}

In the MainPage.xaml add the following code


In viewmodel I have a function save to save the user information. For the time being am not adding any implementation for save function. Our primary aim is to invoke this function from our container application.


So initialize the ViewModel Class in mainpage.xaml.cs file.




public partial class MainPage : UserControl
{
    public ViewModelPerson VMPerson { get; set; }
    public MainPage()
    {
        InitializeComponent();
        VMPerson = new ViewModelPerson();
        this.DataContext = VMPerson.Person;
    }
 
    public void SaveData(object[] objArray)
    {
        VMPerson.Save();
    }
}

Here is the implementation for container application.


Once you done with the user control to be loaded. You have to copy the controlapp.XAP file to web project, that is our third project.


untitled


Now we will start working on the container application.


In Mainpage.caml.cs file contructor download the controlapp.XAP file using the WebClient.


Following is the code snippet;




public MainPage()
{
    InitializeComponent();
    WebClient wClient = new WebClient();
    wClient.OpenReadCompleted += (sender, e) =>
    {
        if ((e.Error == null) && (e.Cancelled == false))
        {
            StreamResourceInfo sRIXap = new StreamResourceInfo(e.Result, null);
            StreamResourceInfo gRSStream = Application.GetResourceStream(sRIXap, new Uri("controlapp.dll", UriKind.Relative));
            AssemblyPart aPart = new AssemblyPart();
            _assembly = aPart.Load(gRSStream.Stream);
            _objectControlApp = _assembly.CreateInstance("controlapp.MainPage") as UserControl;
            OnDemandUserControl.Children.Add(_objectControlApp);
        }
    };
    wClient.OpenReadAsync(new Uri("http://localhost:1105/" + "ClientBin/controlapp.xap"));
}

Use the webslient’s OpenReadAsync method to download the XAP file from the server. In the completed method you have to load the assembly in a assembly variable. Create instance of the class (MainPage) using CreateInstance method of assembly. And finally add the control to stackpanel “OnDemandUserControl”.


So now you got the idea of how to load a external xap/dll in to your application. The next step is to understand how you can access or call a function in that dll / xap file. Lets make it working.


I have added a button in my container application. Here is the code for the button click event handler;




Type[] types = _assembly.GetTypes();
foreach (Type t in types)
{
    MethodInfo[] mInfos = t.GetMethods();
    foreach (MethodInfo minf in mInfos)
    {
        if (minf.Name == "SaveData")
        {
            minf.Invoke(_objectControlApp, null);
        }
    }
}



Above code is to find the function named SaveData and execute it.


minf.Invoke(_objectControlApp, null);


The Invoke function will accept the object you created and the parameters as object array. I do not have any parameter to be supplied, so I am passing null.


Even though this is a very small article, you can use this idea to all of your project. I have found this is a very useful technique every Dot Net programmers should  know.


You guys can download the code here


Thanks Everybody,


HAPPY CODING!!!


Anilal Sambasivan

0 comments:

Post a Comment