Previous month:
February 2005
Next month:
April 2005

March 2005

ASP.NET 2.0 and SharePoint WebParts

ASP.NET 2.0 has great features for WebParts built in. The next version of SharePoint will be based on ASP.NET 2.0 WebParts.

Mike Fitzmaurice has the roadmap for SharePoint and ASP.NET 2.0 WebParts, and what can be done now.

A short summary about what can be done now:

  • don't install ASP.NET 2.0 on a WSS/SPS site before SP2 (WSS/SPS breaks!)
  • ASP.NET 1.1 user controls can be SharePoint WebParts with SmartPart
  • SharePoint WebParts written today will work in WSS v3 (together with ASP.NET 2.0 WebParts)

Christian


C++/CLI: Pointer Arithmetic with Embedded Value Types

With C++/CLI it is possible to use the interior_ptr<> keyword for using pointer arithmetic with value types that are embedded in a managed class.

The array keyword is used to create .NET arrays. Here the array consists of 8 int values.

array<int>^ numbers = gcnew array<int>(8) {1, 1, 2, 3, 5, 8, 13, 21};

Now it would be interesting to iterate through all the elements in the array by using a pointer that references the first element, a pointer that points after the last element, and to use pointer arithmetic to step through all ements: 

int sum(array<int>^ arr)
{
   int* begin = &arr[0];
   int* end = &arr[arr->Length];
   int sum = 0;
   for (; beging != end; begin++)
   {
      sum += *begin;
   }
   return sum;
}

However, because the value types are contained in a managed reference type, the garbage collector may move the array including its contained members to a different memory location. A native pointer cannot be aware of this fact. This is the reason for the new C++/CLI language construct interior_ptr<>. Instead of using a native pointer, an interior_ptr<> can be used to deal with pointer arithmetic with embedded value types:

int sum(array<int>^ arr)
{
   interior_ptr<int> begin = &arr[0];
   interior_ptr<int> end = &arr[arr->Length - 1] + 1;
   int sum = 0;

   for (; begin != end; begin++)
   {
      Console::WriteLine(*begin);
      sum += *begin;
   }
   return sum;
}

A closer look to the declaration of the end variable:

end should point after the last element, such as:

interior_ptr<int> end = &arr[arr->Length];

However, with .NET the bounds of arrays is checked. arr[arr->Length] clearly is out of bounds.

So the last element of the array is referenced with arr->Length - 1, and then pointer arithmetic +1 is used to point to the address after the last element.

interior_ptr<int> end = &arr[arr->Length -1] + 1;

A language construct that makes it easier moving C++ class libraries to .NET.

Christian


Predicates with .NET 2.0

In a previous blog entry I've shown the transformation of the Accumulate method from a traditional implementation to a generic implementation where the action is passed. This was the result of the last version that does something to every object in a collection:

public static TSum Accumulate<TObj, TSum>(
  
IEnumerable<TObj> coll, Action<TObj, TSum> action)
{
   TSum sum = default(TSum);

   foreach (TObj obj in coll)
   {
      sum = action(obj, sum);
   }
   return sum;
}

And this is how this method can be invoked with an anonymous delegate:

decimal amount = Algorithm.Accumulate<Account, decimal>(
   accounts,
   delegate(Account a, decimal sum)
   {
      return a.Balance + sum;
   });

Now I'm extending the implementation of the Accumulate method by using a predicate. A predicate is a method that returns a boolean value. .NET 2.0 defines this generic predicate delegate:

public delegate bool Predicate<T>(T obj);

Such a predicate can be used with the AccumulateIf method to only work with these objects of a collection where the predicate returns true:

public static TSum AccumulateIf<TObj, TSum>(
  
IEnumerable<TObj> coll,
  
Action<TObj, TSum> action
   Predicate<TObj> filter)
{
   TSum sum = default(TSum);

   foreach (TObj obj in coll)
   {
      if (filter(obj))

         sum = action(obj, sum);
   }
   return sum;
}

Now the predicate implementation - the algorithm when the accumulation should happen - can be passed with the method AccumulateIf as anonymous method. In the example the action only happens if the balance has a value greater than 2500.

decimal amount = Algorithm.AccumulateIf<Account, decimal>(
   accounts,
   delegate(Account a, decimal sum) // Action
   {
      return a.Balance + sum;
   },
   delegate (Account a)  // Predicate
   {
      return a.Balance > 2500;

   }
  
);

Christian


Advanced .NET Remoting, Second Edition

Ingo Rammer has done it again - the second edition of Advanced .NET Remoting is available! This time with the help from Mario Szpuszta, a new author from Austria. Mario helped Ingo to update and extend the book to 580 pages (from 404 pages of the first edition). With the extensions this book is also very valuable for readers of the first edition!

The chapters of the second edition:

  • Introduction to .NET Remoting
  • .NET Remoting Basics
  • .NET Remoting in Action
  • Configuration and Deployment
  • Securing .NET Remoting (48 pages from 11)
  • Creating Remoting Clients (new)
  • In-Depth .NET Remoting
  • The Ins and Outs of Versioning (new)
  • .NET Remoting Tips and Best Practices (new)
  • Troubleshooting .NET Remoting (new)
  • Inside the Framework
  • Creation of Sinks
  • Extending .NET Remoting
  • Developing a Transport Channel
  • Context Matters
  • .NET Remoting Usage Reference
  • .NET Remoting Extensibility Reference
  • .NET Remoting Links 

Christian


Project Green Roadmap

Microsoft outlined the roadmap for Project Green:

Wave 1: 2005-2007

  • Common role-based shared user interface with Office integration
  • Interoperability with service-oriented applications
  • SQL Server Reporting Services as the default reporting environment
  • SharePoint Portal Server as intranet or extranet environment
  • The next version of Microsoft CRM is planned for Q4 2005
  • More information about Axapta, Great Plains, Navision...

Wave 2: starts 2008

  • The second wave will build on the innovations of the first wave and bring us a model-driven approach to business processes based on Visual Studio and WinFX.

Tim Brookins was quiet with his blog lately. His latest blog entry from Sep-2004 very good explains the roads of MBF.

Christian


Generic Methods

Following my blog about Generic Delegates and Anonymous Methods, here is more:

Generics and anonymous methods can make code a lot more flexible.

Following I show different ways to accumulate the balance of Account objects. The Account class is a simple class that has a Balance property to access the balance of the class.

1. Summarizing the balance of Account objects in a collection can be done with the Accumulate method:

public static decimal Accumulate(IEnumerable e)
{
   decimal sum = 0;
   foreach (Account a in e)
   {
      sum += a.Balance;
   }
   return sum;
}

Invoking the method, the Account collection is passed:

decimal amount = Algorithm.Accumulate(accounts);

2. Making this method generic that it is possible to use other than Account objects, a generic method Accumulate can be implemented. However, because the Balance property is accessed for the accumulation, all generic TAccount classes must offer this property as is defined with the constraint IAccount.  

public static decimal Accumulate<TAccount>(IEnumerable<TAccount> coll)
   where TAccount : IAccount
{
   decimal sum = 0;
   foreach (TAccount obj in coll)
   {
      sum += obj.Balance;
   }
   return sum;
}

Invoking the method is not different to before:

decimal amount = Algorithm.Accumulate(accounts);

3. The second version has the requirement that all objects that are accumulated implement the Balance property. This can be more flexible by defining a generic delegate that defines the action.

Now the Accumulate mehtod can do anything to any object of a collection. What is done to the objects is defined with the delegate Action<>(). This Action delegate defines two parameters and a return type.

public delegate TSum Action<TObj, TSum>(TObj obj, TSum sum);

public static TSum Accumulate<TObj, TSum>(
  
IEnumerable<TObj> coll, Action<TObj, TSum> action)
{
   TSum sum = default(TSum);

   foreach (TObj obj in coll)
   {
      sum = action(obj, sum);
   }
   return sum;
}

To do the same as before - adding all balances - the implementation of the Action can be defined as anonymous method calling the Accumulate method.

decimal amount = Algorithm.Accumulate<Account, decimal>(
   accounts,
   delegate(Account a, decimal sum)
   {
      return a.Balance + sum;
   });

This is really flexible as it is not only possible to use Account objects, but any object. Instead of accumulating some values anything else can be done, too.

Of course anonymous methods should only be used with very simple implementations that are not needed somewhere else. Instead of anonymous methods a normal method can be used, too.

Christian


Generic Delegates and Anonymous Methods

Generics and anonymous methods are great improvements of C#.

Having a generic collection persons of type List<Person>, the objects of the collection can be accessed with a simple foreach statement:

foreach (Person p in persons)
{
   Console.WriteLine(p);
}

The collection class also has a ForEach method that can be used instead of a foreach statement. The ForEach method has the parameter Action<T> action. Action is a generic delegate:
public delegate void Action<T>(T obj);

Using Person objects in the collection, the method that can be invoked by the delegate looks like this:

void DisplayPerson(Person p)
{
   Console.WriteLine(p);
}

Now this method can be passed to the ForEach method:

persons.ForEach(new Action<Person>(DisplayPerson));

The same can be done with fewer characters as the delegate type is inferred if possible:

persons.ForEach(DisplayPerson);

If the method that is invoked by ForEach is not used on other places, it can be implemented as an anonymous method:

persons.ForEach(delegate(Person p)
{
   Console.WriteLine(p);
});

Christian