Label Cloud

Friday, December 21, 2007

Closing and Terminating views in SCSF

There is a bug in the SCSF implementation that views even though closed, will not terminate the workitems. This was described on codeplex in the following thread: http://www.codeplex.com/smartclient/Thread/View.aspx?ThreadId=4370

Here is my workaround:

In the View.Designer.cs

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (_presenter != null)
{
_presenter.OnCloseView(); // <<<<<<<<======= Workaround
_presenter.Dispose();
}

if (components != null)
components.Dispose();
}

base.Dispose(disposing);
}

In the ViewPresenter.cs

bool Closing = false;
public void OnCloseView()
{
if (!Closing)
{
Closing = true;
if (WorkItem.Status != WorkItemStatus.Terminated)
WorkItem.Terminate();

base.CloseView();
}
}

The code will force the workitem to be terminated after the view is closed

Technorati Tags: , ,


Share/Save/Bookmark

Thursday, December 20, 2007

Compiling .NET 3.5 code to .NET 2.0 Works

This is something that is totally cool. You can use Visual Studio 2008 and a lot of the new functionality and cross compile it to .NET 2.0 and run it on the older framework. For Example, You can use Var objects, Simple Property Declarations, Property Constructors, Lambda expressions

Here's an example program that can be compiled with VS 2008 to the .NET 2.0 framework

static class Program
    {
        private class Client
        {
            public string Name { get; set; }
            public string Address { get; set; }
        }

        private static List<Client> clients = new List<Client>
        {
            new Client() {Name = "Name1", Address = "Address1" },
            new Client() {Name = "Name2", Address = "Address2" },
            new Client() {Name = "Name3", Address = "Address3" },
            new Client() {Name = "Name13", Address = "Address13" },
            new Client() {Name = "Name123", Address = "Address123" }
        };

        [STAThread]
        static void Main()
        {
            List<Client> ClientsWith1 = clients.FindAll(c => c.Name.Contains("1"));
            ClientsWith1.ForEach(c =>
            {
                var NewClient = new
                {
                    Name = c.Name,
                    Address = c.Address
                };
                Console.WriteLine(NewClient.ToString());
            });
            Console.ReadKey();
        }
    }
 
Here's the output

{ Name = Name1, Address = Address1 }
{ Name = Name13, Address = Address13 }
{ Name = Name123, Address = Address123 }

And it works without .NET 3.5 installed.

For those interested, Here's a Reflected code

internal static class Program
{
    // Fields
    private static List<Client> clients;
    [CompilerGenerated]
    private static Predicate<Client> CS$<>9__CachedAnonymousMethodDelegate2;
    [CompilerGenerated]
    private static Action<Client> CS$<>9__CachedAnonymousMethodDelegate3;

    // Methods
    static Program()
    {
        List<Client> <>g__initLocal4 = new List<Client>();
        Client <>g__initLocal5 = new Client();
        <>g__initLocal5.Name = "Name1";
        <>g__initLocal5.Address = "Address1";
        <>g__initLocal4.Add(<>g__initLocal5);
        Client <>g__initLocal6 = new Client();
        <>g__initLocal6.Name = "Name2";
        <>g__initLocal6.Address = "Address2";
        <>g__initLocal4.Add(<>g__initLocal6);
        Client <>g__initLocal7 = new Client();
        <>g__initLocal7.Name = "Name3";
        <>g__initLocal7.Address = "Address3";
        <>g__initLocal4.Add(<>g__initLocal7);
        Client <>g__initLocal8 = new Client();
        <>g__initLocal8.Name = "Name13";
        <>g__initLocal8.Address = "Address13";
        <>g__initLocal4.Add(<>g__initLocal8);
        Client <>g__initLocal9 = new Client();
        <>g__initLocal9.Name = "Name123";
        <>g__initLocal9.Address = "Address123";
        <>g__initLocal4.Add(<>g__initLocal9);
        clients = <>g__initLocal4;
    }

    [STAThread]
    private static void Main()
    {
        if (CS$<>9__CachedAnonymousMethodDelegate2 == null)
        {
            CS$<>9__CachedAnonymousMethodDelegate2 = delegate (Client c) {
                return c.Name.Contains("1");
            };
        }
        if (CS$<>9__CachedAnonymousMethodDelegate3 == null)
        {
            CS$<>9__CachedAnonymousMethodDelegate3 = delegate (Client c) {
                Console.WriteLine(new { Name = c.Name, Address = c.Address }.ToString());
            };
        }
        clients.FindAll(CS$<>9__CachedAnonymousMethodDelegate2).ForEach(CS$<>9__CachedAnonymousMethodDelegate3);
        Console.ReadKey();
    }

    // Nested Types
    private class Client
    {
        // Fields
        [CompilerGenerated]
        private string <Address>k__BackingField;
        [CompilerGenerated]
        private string <Name>k__BackingField;

        // Properties
        public string Address
        {
            [CompilerGenerated]
            get
            {
                return this.<Address>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.<Address>k__BackingField = value;
            }
        }

        public string Name
        {
            [CompilerGenerated]
            get
            {
                return this.<Name>k__BackingField;
            }
            [CompilerGenerated]
            set
            {
                this.<Name>k__BackingField = value;
            }
        }
    }
}
 
Technorati Tags: ,,,,


Share/Save/Bookmark

Calculating Hashvalues for files the way .NET does for the Application Manifest

hey

I had to write a custom download component to download modules for a ClickOnce deployed application. The actual downloading is simple, the tricky part was creating the manifest and make sure that I only download files that are required.

I am using an GeneraApplicationManifest MSBuild task to generate an application manifest. The documentation is very easy to follow.

The generated manifest will include a Hash value. It is fairly simple to compute the same hash value manually and be able to validate it.

private bool HashChanged(string fileName, string originalHashValue)
        {
            byte[] Hash = Convert.FromBase64String(originalHashValue));
            byte[] newHash;
            SHA1Managed sha = new SHA1Managed();
         
            FileStream strm = null;
            try
            {
                strm = new FileStream(fileName, FileMode.Open, FileAccess.Read);         
                newHash = sha.ComputeHash(strm);
            }
            finally
            {
                if (strm != null)
                    strm.Close();
            }

            if (Hash.Length != newHash.Length)
                return true;
            for(int i = 0; i< Hash.Length; i++)
            {
                if (Hash[i] != newHash[i])
                    return true;
            }
            return false;
        }
Technorati Tags: ,,,


Share/Save/Bookmark

Wednesday, December 05, 2007

Subversion pre-revprop-change hook

Another small batch file hook for those running subversion on windows. This hook will allow users to update a log message on the old check-in.

Note: Property changes are not versioned, so you will permanently loose the old message.

Place this in a pre-revprop-change.cmd
-------------
IF %5 EQU M GOTO CONT1
GOTO FAIL
:CONT1
IF %4 EQU svn:log GOTO OK
:FAIL
echo "Changing revision properties other than svn:log is prohibited" >&2
exit 1
:OK
exit 0
------------

 

Technorati Tags: , ,


Share/Save/Bookmark

Creating a ClickOnce Smart Client CAB Based (SCSF) application with Environment Overrides

My application is distributed via ClickOnce and a requirement is to be able to provide endpoint overrides for multiple environments. Here's what was done to create the solution


Smart Client Software Factory includes a service called EndpointCatalog. It allow for easy management of endpoints with environment overrides. Start by adding a Microsoft.Practices.SmartClient.EndpointCatalog.dll as a reference to Infrastructure.Module. Then open ModuleController class in and register the EndpointCatalog service.

private void AddServices()
{
IEndpointCatalog catalog = WorkItem.RootWorkItem.Services.Get<IEndpointCatalog>(false);
if (catalog == null)
{
IEndpointCatalogFactory catalogFactory =
new EndpointCatalogFactory("Endpoints");

catalog = catalogFactory.CreateCatalog();
WorkItem.RootWorkItem.Services.Add<IEndpointCatalog>(catalog);
}

This will read the endpoint catalog from the application.config file , section Endpoints. Here is a partial app.config

<configSections>
<section name="Endpoints" type="Microsoft.Practices.SmartClient.EndpointCatalog.Configuration.EndpointSection, Microsoft.Practices.SmartClient.EndpointCatalog" />
</configSections>

<Endpoints>
<EndpointItems>
<add Name="DataService.DataClient"
Address="http://server/DataService.svc"
UserName="default-user-name" Password="default-password" Domain="default-domain">
<NetworkItems>
<add Name="QA" Address="http://qa.server/DataService.svc"/>
<add Name="UAT" Address="http://uat.server/DataService.svc"/>
</NetworkItems>
</add>
</EndpointItems>
</Endpoints>

The endpoints section defines an endpoint, and an override for each environment. The catalog will return the override if it exists, or the original entry if it does not.

To create the WCF client, I created the following function.

T CreateWCFClient<T, Ti>()
where T : ClientBase<Ti>, new()
where Ti : class
{
try
{
T client = new T();
if (endpointCatalog.EndpointExists(typeof(T).FullName))
{
client.Endpoint.Address = new EndpointAddress
(endpointCatalog.GetAddressForEndpoint(typeof(T).FullName, Environment));
}
return client;
}
catch (Exception)
{
throw;
}
}

Add the required service to the module that will hold the function and you are almost done. The request to create the client is as follows.

_DataWebService = CreateWCFClient<DataService.DataClient, DataService.IDataClient>();

Please comment for any questions, I'll try to clarify


Share/Save/Bookmark

Tuesday, December 04, 2007

www.tfanshteyn.com redirection

I finally implemented a javascript redirection on the www.tfanshteyn.com to blog.tfanshteyn.com


Share/Save/Bookmark

Chat with me

Something new I've just added to my blog webpage, the "Chat with me" link. It is in the right top corner of the site.

ChatWithMe

You can implement this functionality by http://settings.messenger.live.com/applications/websettings.aspx


Share/Save/Bookmark