Показаны сообщения с ярлыком dotNet. Показать все сообщения
Показаны сообщения с ярлыком dotNet. Показать все сообщения

среда, июля 13, 2011

Sharepoint 2010 и пустые значения SPFieldLookup и SPFieldLink

Тут недавно обнаружил что если очистить поле Lookup или Ссылка в записи списка. То вместо пустого значения пишется не null а "0;#" для Lookup и "," для Ссылки. А во время создания поле будет задано как null.
Скажу более - данное поведение зависит от браузера. Таким образом в пустом значении этих полей может оказаться как null так и  "0;#"или ",".
Далее привожу пример функции проверки на пустые значения:

public static class NullComparer{
       public bool IsEmptyValue(object value){
              var strval=string.Format("{0}",value).Trim();
              if(value==null ||
                 string.IsNullOrEmpty(strval) ||
                 strval == "," ||
                 strval == "0;") return true;
              return false;
       }
}

вторник, июля 12, 2011

Настройка GZIP для IIS ASP.NET приложений в web.config

Можно включить GZIP сжатие из web.config сайта\приложения. Очень полезно на shared хостингах

<system.webServer>
<httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
<scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
<dynamicTypes>
<add mimeType="text/*" enabled="true"/>
<add mimeType="message/*" enabled="true"/>
<add mimeType="application/javascript" enabled="true"/>
<add mimeType="*/*" enabled="false"/>
</dynamicTypes>
<staticTypes>
<add mimeType="text/*" enabled="true"/>
<add mimeType="message/*" enabled="true"/>
<add mimeType="application/javascript" enabled="true"/>
<add mimeType="*/*" enabled="false"/>
</staticTypes>
</httpCompression>
<urlCompression doStaticCompression="true" doDynamicCompression="true"/>
</system.webServer>

Для проверки работы убедитесь в том, что у страниц сайта появился заголовок:
Content-Encoding: gzip

суббота, июня 25, 2011

Новая технологическая демонстрация. SLAR + SL5

Итак. Поигравшись с Balder для Sliverlight 4, я понял - он не справляется с производительностью. Было принято решение перейти на Silverlight 5 XNA. Что дало приличный прирост производительности. Правда все еще не перенесены некоторые ф-ции (залипание объекта, множественные одинаковые теги).
Создана демонстрация концепции интерактивного объекта смешанных реальностей (Визитка\Портфолио).

Новые вопросы:

  1. Правильное положение и дизайн логотипа.
  2. Как правильно активировать объекты портфолио (сами картинки).
  3. Дизайн и носитель карточки.
  4. Возможность дальнейшего уменьшения элементов карточки.

пятница, июня 24, 2011

Вернулись времена коротких путей.

Сегодня при попытке использовать msbuild словил.
Error 14 The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters. [C:\Users\holinov\Desktop\SRC\Layer1\MRR.DVIZ\trunk\src\Mrr.Dviz.LookupFieldWithPicker \LookupFieldWithPicker\Mrr.Dviz.LookupFieldWithPicker.csproj] C:\Users\holinov\Desktop\SRC\Layer1\MRR.DVIZ\trunk\src\Mrr.Dviz.Deploy\Mrr.Dviz.Setup.DeployAction\> C:\Users\holinov\Desktop\SRC\Layer1\MRR.DVIZ\trunk\src\Mrr.Dviz.LookupFieldWithPicker\ LookupFieldWithPicker\Package\Package.package Mrr.Dviz.Setup.DeployAction
Мда, я думал такие времена уже прошли. Придется искать workaround.

суббота, июня 04, 2011

Серия статей про Augmented Reality. Моя точка зрения.

Начинаю публикацию результатов моих исследовательских работ связанных с концепциями AR (Augmentet reality), NUI (Natural User Interface).
Идея концепции которую я хочу проверить состоит в построении системы пользовательского интерфейса на принципах смешанных реальностей. В теории пользователь, для удовлетворения своих информационных потребностей, должен производить действия не с экранными объектами , а с объектами реального или виртуального-трехмерного миров(реальностей).  Пользователь может воздействовать на объекты виртуального мира посредством воздействия на объекты реального мира (AR-теги), путем относительных перемещений, вращения или внесения новых AR-тегов. А так-же распознания трехмерного положения пользователя относительно виртуальных объектов производимых системой Kinekt или подобной ей.
Для проверки данной концепции были выбраны следующие технологические платформы:

  1. Система смешивания реальностей построена на AR-тегах. ( ARToolkit: Реализация SLARToolkit )
  2. Система 3D визуализации ( Balder , Silverlight 5 XNA ) 

Список опубликованных мною материалов по данному  исследованию: (все видео в статьях)
  1. Первые результаты экспериментов SLARToolkit + Blader + Концепция
  2. Демонстрация концепции интерактивного объекта смешанных реальностей

воскресенье, мая 15, 2011

Sharepoint 2010 и русские имена столбов списков

Если вы сталкивались с написанием CAML запросов для Sharepoint 2010 то знаете, что обращение к столбцам с русскими именами достаточно затруднительно т.к. если столбец создавался изначально с русским именем то его внутреннее имя будте представленно закодированным значением. Например если вы назвали свой столбец "Столбец" то его внутренним именем будет : _x0421__x0442__x043e__x043b__x0431__x0435__x0446_.
Я часто сталкиваюсь с такой белибердой и выяснил что это на самом деле HEX значение Unicode символов окруженные _х и _ . Вооружившись этим знанием я написал две функции для преобразования строки туда и обратно:

public static class NameConverter
    {
        /// <summary>
        /// Расшифровать имя из внутреннего представления
        /// </summary>
        /// <param name="val">Закодированое имя</param>
        /// <returns>Расшифрованое значение</returns>
        public static string DecodeName(string val)
        {
            val = val.Replace("ows", "");
            if (!val.Contains("_x")) return val;

            var sb = new StringBuilder();
            val = val.Replace("_", "");
            var parts = val.Split(new[] { 'x' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string part in parts)
            {
                int v = int.Parse(part, NumberStyles.HexNumber);
                var c = (char)v;
                sb.Append(c);
            }
            return sb.ToString();
        }
        /// <summary>
        /// Закодировать русскую строку
        /// </summary>
        /// <param name="name">Имя для кодирования</param>
        /// <returns>Закодированое значение</returns>
        public static string EncodeName(string name)
        {
            var sb = new StringBuilder();
            for (int i = 0; i < name.Length; i++)
            {
                sb.AppendFormat("_x{0:x4}_", (int)name[i]);
            }
            return sb.ToString();
        }
    }

суббота, апреля 30, 2011

Удаление элементов из SPList через ProcessBatchData

Всем разработчикам Sharepoint 2010 (да и вообще любой версии Sharepoint или MOSS) известна ситуация с медленной работой объектной модели и большом времени поиска\модификации через нее.
Так вот мне однажды пришлось писать систему массового удаления данных из разных списков сайта под управлением Sharepoint 2010. Решения через SPListItem.Delete(), SPList.Items.DeleteItem(idx) и даже SPList.Items.DeleteItemById(itemId) давали жуткие показатели времени работы (удаление 100 элементов за 60000(!)-120000(!) секунд). И тут я вспомнил про волшебную возможность SPWeb.ProcessBatchData которая позволяет выполнять CAML запросы напрямую, минуя слой объектной модели.( Забегая вперед скажу что такое решение мне дало производительность в районе ~650сек на 5000 записей.)
Что-ж покопав документацию на сайте Microsoft (http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.processbatchdata.aspx) я подумал что все тривиально и создал свое первое решение. Радостно посапывая я ткнул в кнопочку деплой и запустил свой код. Как ни странно код рухнул. Не буду описывать процесс поиска ошибки и сразу скажу: Разбивайте свои запросы на пачки! Не больше 180 запросов в одном теге . Лично я разбиваю свои запросы в пачки по 100.
Поправив код и сделав разбиение на пачки я запустил все снова. Как и ожидалось пепелац не взлетел. А я поимел совершенно смутившую меня ошибку ArgumentException. Тут надо отметить удивительную абсолютную невразумительности сообщений Sharepoint об ошибках.
Вот к примеру как выглядел мой Expcetion
Exception type: ArgumentException
[Message] = "0x80070057"
[ParamName] = ""
[Data] = "System.Collections.ListDictionaryInternal"
[TargetSite] = "Void GetListItemDataWithCallback2(Microsoft.SharePoint.Library.IListItemSqlClient, System.String, System.String, System.String, System.String, Microsoft.SharePoint.Library.SAFEARRAYFLAGS, Microsoft.SharePoint.Library.ISP2DSafeArrayWriter, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Microsoft.SharePoint.Library.ISPDataCallback, Boolean ByRef)"
[StackTrace] = "   в Microsoft.SharePoint.Library.SPRequestInternalClass.GetListItemDataWithCallback2(IListItemSqlClient pSqlClient, String bstrUrl, String bstrListName, String bstrViewName, String bstrViewXml, SAFEARRAYFLAGS fSafeArrayFlags, ISP2DSafeArrayWriter pSACallback, ISPDataCallback pPagingCallback, ISPDataCallback pPagingPrevCallback, ISPDataCallback pFilterLinkCallback, ISPDataCallback pSchemaCallback, ISPDataCallback pRowCountCallback, Boolean& pbMaximalView)
   в Microsoft.SharePoint.Library.SPRequest.GetListItemDataWithCallback2(IListItemSqlClient pSqlClient, String bstrUrl, String bstrListName, String bstrViewName, String bstrViewXml, SAFEARRAYFLAGS fSafeArrayFlags, ISP2DSafeArrayWriter pSACallback, ISPDataCallback pPagingCallback, ISPDataCallback pPagingPrevCallback, ISPDataCallback pFilterLinkCallback, ISPDataCallback pSchemaCallback, ISPDataCallback pRowCountCallback, Boolean& pbMaximalView)
   в Microsoft.SharePoint.SPListItemCollection.EnsureListItemsData()
   в Microsoft.SharePoint.SPListItemCollection.GetEnumerator()
   в MRR.DVIZ.Workflows.ClearFormsWorkflow.ClearFormsWorkflow.FindRunning(Object sender, EventArgs e)
   в System.Workflow.ComponentModel.Activity.RaiseEvent(DependencyProperty dependencyEvent, Object sender, EventArgs e)
   в System.Workflow.Activities.CodeActivity.Execute(ActivityExecutionContext executionContext)
   в System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext)
   в System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext)
   в System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime)
   в System.Workflow.Runtime.Scheduler.Run()"
[HelpLink] = ""
[Source] = ""
Поиски google ничего вразумительного не дали. Правда у меня зародилось смутное сомнение в том что я что-то не так делаю с форматом CAML запроса. Я даже не могу сказать что мена натолкнуло на эту мысль, интуиция если только.
Не буду рассказывать свои танцы вокруг подбора нового формата. скажу лишь что:
<Batch OnError="Continue">

<SetList>b15da36c-6ed8-4fe1-bbcc-89a1996c1dbe</SetList>
<Method ID="1" Cmd="Delete"><Field Name="ID">638</Field></Method>
<Method ID="2" Cmd="Delete"><Field Name="ID">639</Field></Method>
<Method ID="3" Cmd="Delete"><Field Name="ID">648</Field></Method>
<Method ID="4" Cmd="Delete"><Field Name="ID">649</Field></Method>
<Method ID="5" Cmd="Delete"><Field Name="ID">650</Field></Method>
<Method ID="6" Cmd="Delete"><Field Name="ID">651</Field></Method>
<Method ID="7" Cmd="Delete"><Field Name="ID">652</Field></Method>
<Method ID="8" Cmd="Delete"><Field Name="ID">653</Field></Method>
<Method ID="9" Cmd="Delete"><Field Name="ID">654</Field></Method>
<Method ID="10" Cmd="Delete"><Field Name="ID">655</Field></Method>
<Method ID="11" Cmd="Delete"><Field Name="ID">656</Field></Method>
<Method ID="12" Cmd="Delete"><Field Name="ID">657</Field></Method>

</Batch>
не красиво но не правильно. Надо:
<?xml version="1.0" encoding="UTF-8"?>

<Batch OnError="Return">
<Method ID="1,Del"><SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">20</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="2,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">21</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="3,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">22</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="4,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">23</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="5,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">24</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="6,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">25</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="7,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">26</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="8,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">27</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="9,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">28</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="10,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">29</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="11,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">30</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>
<Method ID="12,Del"> <SetList 
Scope="Request">465ebd0a-d6d4-4736-81d7-27cac86e8952</SetList> <SetVar 
Name="ID">31</SetVar><SetVar Name="Cmd">Delete</SetVar></Method>

</Batch>
Код создающий такую структуру и выполняющие его в пачках (listMods - IEnumerable с ИД строк для уделания):
List<string> listBatch = new List();

StringBuilder batch = new StringBuilder();
StringBuilder log = new StringBuilder();

if (!string.IsNullOrEmpty(listTitle) && listMods != null && listMods.Count > 0)
{
    log.AppendFormat("Очистка списка {0}. Удалеине {1} элементов.", listTitle, listMods.Count);
    batch.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
    batch.AppendLine("<Batch OnError=\"Return\">");
    int batchSize = 0;
    foreach (int toDelete in listMods)
    {
        batchSize++;
        batch.AppendFormat(
            "<Method ID=\"{0},Del\"> {2} <SetVar Name=\"ID\">{1}</SetVar><SetVar Name=\"Cmd\">Delete</SetVar></Method>",
            batchSize, toDelete,
            string.Format("<SetList Scope=\"Request\">{0}</SetList>",
                            queryRoot.Lists[listTitle].ID))
            .AppendLine();

        if (batchSize >= 100)
        {
            batch.AppendLine("</Batch>");
            listBatch.Add(batch.ToString());
            batchSize = 0;

            batch = new StringBuilder(batch.Capacity);
            batch.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            batch.AppendLine("<Batch OnError=\"Return\">");
        }
    }
    batch.AppendLine("</Batch>");
    listBatch.Add(batch.ToString());


    foreach (string cmd in listBatch)
    {
        try
        {
            log.Append("Исполнение запроса :").AppendLine().Append(cmd).AppendLine();
            string cmd1 = cmd;
            SPSite siteColl = currentSite;
            SPWeb site = currentWeb;
            SPSecurity.RunWithElevatedPrivileges(delegate()
                                                        {
                                                            using (
                                                                SPSite ElevatedsiteColl =
                                                                    new SPSite(siteColl.ID))
                                                            {
                                                                using (
                                                                    SPWeb ElevatedWeb =
                                                                        ElevatedsiteColl.OpenWeb(
                                                                            site.ID))
                                                                {
                                                                    ElevatedWeb.ProcessBatchData(cmd1);
                                                                }
                                                            }
                                                        });                                
        }
        catch (Exception e)
        {
            var ex = new ApplicationException("Ошибка при исполнении комманды: " + cmd, e);
            throw ex;
        }
    }
}

среда, апреля 06, 2011

Sharepoint 2010 и исключение file not found exception

Маленький совет: Если вы пишите приложение использующее объектную модель Sharepoint и при попытке открыть сайт как в примере:
using(SPSite sirte=new SPSite("http://site"){
......
}
И получаете исключение File not fount exception хотя сайт в браузере открывается - проверьте две вещи:

  1. Build platform для проекта должен быть .NET Framework 3.5
  2. Проект обязательно собираться для x64 платформы

среда, июля 14, 2010

Проект netBot - C# проект по управлению роботами

Объявляю о создании проекта посвященному робототехнике.
Проект - система позволяющая управлять роботом и писать алгоритмы для автономного управления роботом на языке C#.
Система должна включать в себя

  1. Подсистему общения с сенсорами
  2. Подсистему движения\позиционирования
  3. Подсистему компьютерного зрения
Так-же система должна включать в себя спецификацю на устройства\сенсоры и спецификацию на драйвера к этим устройствам.
Дальнейший анализ требований буду проводить здесь-же - в моем блоге

вторник, июля 13, 2010

Система ведения логов

Приглядевшись к своим исходникам я понял что нечто подобное всегда приходится делать некую систему для ведения логов необходимых для отладки. И вот я решил обобщить все что я использовал в своих проектах до этого и выделить в отдельную библиотеку классов.


Требования

  1. Конфигурация должна быть легкой
  2. Система должна быть легко расширяема
  3. Система должна предоставлять множественные способы вывода данных
  4. Система должна обладать возможностью перехвата необработанных исключений
  5. Система должна иметь статический и нестатический интерфейсы.

Архитектура



Принятые решения по архитектуре можно увидеть на приведенной ниже диаграмме: Структура классов


Интересные места


Перехват исключений
/// <summary>
/// Установить перехватчик исключений на заданный домен приложений
/// </summary>
/// <param name="dom"> </param>Домен для установки перехватчика
public void SetupIntercept( AppDomain dom )
{  
 dom.UnhandledException += ( s, e ) => {     
  Logger.Instance.Log(new LogMsg() {      
   Exception = (Exception)e.ExceptionObject, 
   Lvl = 100,
   Msg = "------ Unhandled Exception ------\n"
  }); 
 };

 dom.FirstChanceException += ( s, e ) => {
  Logger.Instance.Log(new LogMsg()
  {
   Exception = e.Exception,
   Lvl = 80,
   Msg = "------ First Chance Exception ------\n"
  }); 
 };
}

Дальнейшее развитие



  • Канал для записи данных в Базу данных
  • Канал позволяющий передавать сообщения на внешний сервер
  • Приложение - сервер логов


Если у вас есть вопросы - пишите. Исходники тут


C# 4.0 Новое в языке


Новые возможности .NET 4.0: C# 4.0

После выхода Visual Studio 2010 beta 1 - первым делом нужно разобраться, что же дает нового нам C# 4.0 (так как это мой основной язык программирования - для меня это является важным). Первым делом должен вам порекомендовать примеры C# 4.0, которые можно скачать отсюда (там же есть документ New Features in C# 4.0, которая послужила основой для этого топика). Документацию по .Net Framework 4.0 beta 1 можно посмотреть в MSDN. Дальше будут следовать мой небольшой опыт знакомства с новой версией .NET.

1. Dynamic Language Runtime

Изначально стоит взглянуть на следующую схему, иллюстрирующую архитектуру DLR: 
Именно! Теперь в .net можно еще и скриптовые языки использовать, такие как IronRuby и IronPython. Не думаю, что я буду этим пользоваться, но любителям экзотики предоставляю ссылки:
  • IronPython. - open-source проект на CodePlex.
  • IronRuby. - open-source проект на RubyForge.
Более того, предоставляется исходники DLR, при помощи которых вы, наверняка, сможете создать свой динамический язык для .NET, если вам это необходимо
Итак DLR включает в себя Expression Trees, которые просто являются представлением вызовов методов или бинарных операций в виде дерева, их функциональность можно посмотреть на следующем примере:
Expression<int, bool>> exprTree = num => num < 5;
// Decompose the expression tree.
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
               param.Name, left.Name, operation.NodeType, right.Value);
В этом примере мы сначала описываем лямбда выражение x=>x<5, а затем при помощи объектов от Expression Trees разбираем данное выражение.
Call Site caching в DLR - это, насколько я понимаю, и есть динамическое представление вызовов методов динамических объектов или операций над динамическим объектами. DLR кеширует характеристики объектов (о типах объектах), а так же об операции, и если данная операция уже была выполнена ранее, тогда всю необходимую информацию DLR получит уже из кеша (вот как то так).
И последнее в DLR это набор классов, интерфейсов: IDynamicMetaObjectProvider, DynamicMetaObject, DynamicObject и ExpandoObject. Давайте опять посмотрим на примере, как нам это может пригодиться, и зачем нам вообще нужен этот DLR:
class Test1
{
}
 
static void Main(string[] args)
{
  dynamic t = new Test1();
  string str = t.Hello(); // Error 1 
 
  dynamic d = 7.0;
  int i = d; // Error 2
}
На удивление данный код скомпилируется и запустится. Все дело в волшебном слове dynamic, оно нам позволяет вызывать любые по имени свойства или методы, а так же приводить объект к любому типу. Во время Runtime (выполнения кода) вылетят ошибки, Error 1: о том, что метод не найден, Error 2: о том, что double невозможно привести к int. Попробуем их исправить:  для исправления первой ошибки наш класс Test1 отнаследуем от типа System.Dynamic.DynamicObject и перегрузим один из методов, для исправления второй просто явно укажем преобразование типов:
class Test1 : DynamicObject
{
  public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
  {
    if (binder.Name == "Hello")
    {
      result = "Test1 is Dynamic Object!";
      return true;
    }
    return base.TryInvokeMember(binder, args, out result);
  }
}
 
static void Main(string[] args)
{
  dynamic t = new Test1();
  string str = t.Hello(); 
 
  dynamic d = 7.0;
  int i = (int) d;
}
Теперь наш код будет работать. Переменная str получить значение "Test1 is dynamic object!", а i значение 7.
Конечно, необязательно наследоваться от класса DynamicObject, можно отнаследоваться и от интерфейсаIDynamicMetaObjectProvider, но тогда нужно будет самому реализовывать метод  DynamicMetaObject GetMetaObject(Expression parameter), и более того реализовывать свой тип, унаследованный от DynamicMetaObject, ну в любом случае варианты есть - так что можно взять на вооружение.

2. Именованные и необязательные параметры в методах

Это достаточно простая функциональность и уже много где оговорена, она хорошо описана вот например тут (на русском языке одним из автором хабрахабра). Если парой слов, то это возможность устанавливать дефолтные значения у параметров методов, а так же возможность установки значения параметра по имени при вызове метода. В общем пример будет лучшим объяснением:
class Test1 
{
  public void Method(int a = 0, string b = "Hello", bool c = true)
  {
    Console.WriteLine("{0}, {1}, {2}", a, b, c);
  }
}
 
static void Main(string[] args)
{
  Test1 o = new Test1();
  // Вызовем по как обычно
  o.Method(1, "Hello", true);
  // А можно поменять порядок параметров
  o.Method(b: "hello", c: true, a: 1);
  // Можно вообще ничего не вызывать
  // (установлены значения по умолчанию у всех параметров)
  o.Method();
  // Можно определить только необходимые параметры
  o.Method(1, "Hello");
  // И не обязательно по порядку
  o.Method(c: false);
}
Теперь из- за переименование параметра метода, код может и не скомпилироваться, если кто-то использовал установку значения по имени, так что нужно быть аккуратнее. Я рад дефолтным значениям, и постараюсь не использовать функциональность именованных параметров.
В дополнение хочу сказать, что если все таки будет у класса Test1 метод void Method(int a), тогда при вызове o.Method(1)вызовится именно он, а не метод из примера с дефолтными значениями.

3. Возможности для COM Interop

DLR так же дал новые возможности для COM Interop, теперь  можно COM объекты определять как динамические (точнее они уже являются в большинстве своем динамического типа) и не приводить постоянно получаемые объекты к определенным типам для вызова методов или свойств.
excel.Cells[1, 1].Value = "Hello";
// вместо 
((Excel.Range)excel.Cells[1, 1]).Value2 = "Hello";
Данный пример взят из документа New Futures in C# 4.0 С одной стороны приятно, что теперь не нужно мучаться и находить к какому же типу нужно привести объект, чтобы вызвать его свойство или метод, но с другой стороны теряется IntelliSense.

4. Новое в generic

Теперь обогатился и generic новой функциональностью. Можно теперь у интерфейсов и у делегатов перед определением generic типов писать out и in, зачем это чуть дальше, а сначала рассмотрим пример.
При работе с generic часто хочется сделать что то типа такого:
IList<string> strings = new List<string>();
IList<object> objects = strings;
Но нельзя. Потому, что следом можно написать:
objects[0] = 5;
string s = strings[0];
То есть, изначально у нас был список строк, потом обозначили его как список объектов, и хотим уже работать с ним, как с объектами, устанавливая любой другой объект в него, хотя список до сих пор является списком строк.
Но, если вдуматься, то можно представить, что если бы список был только для чтения, то мы бы уже не смогли ничего нарушить, и там бы логика была ясна, потому следующий код на C# 4.0 будет работать:
IEnumerable<object> objects = strings;
Огромную полезность данная функциональность принесет в работе с linq, там часто возникают проблемы, что возвращаем объекты одного типа, а нужно получить список другого типа (базового).
Итак, как же такое стало возможным. Сначала рассмотрим слово out. Теперь интерфейс IEnumerable объявлен какIEnumerable, где out обозначает, что тип T может быть использован только для возвращения значений, в другом случае компилятор будет ругаться, ну и более того это дает нам, что интерфейс IEnumerable так же есть и IEnumerable, если у A есть возможность приведения типа к B, если на простом примере, то IEnumerable, есть теперь и IEnumerable. Вот пример:
public interface IEnumerable<out T> : IEnumerable
{
  IEnumerator GetEnumerator();
}
public interface IEnumerator<out T> : IEnumerator
{
  bool MoveNext();
  T Current { get; }
}
Есть еще слово in. Его так же можно использовать в описании generic делегатов и интерфейсов. Несет оно такую же смысл как и слово out, только в данному случае описанный тип можно использовать только в передаче параметров, вот пример:
public interface IComparer<in T>
{
  public int Compare(T left, T right);
}
То есть в данном случае, если IComparer может считаться и IComparer, потому как если уж он может сравнивать объекты типа object, то и string тоже может.
Так же, как я уже сказал, слова out и in можно применять и к интерфейсам, так, например:
public delegate TResult Func<in TArg, out TResult>(TArg arg);

Заключение

Так же в .NET 4.0 появилось много новвовведений, таких как  Lazy Initialiation - память под объект выделяется тогда, когда это действительно становится нужно. Появились новые типы, как например, BigInteger - теперь не нужно для лабораторных работ студентам писать свои классы для работы с большими числами ;), SortedSet - класс представляет собой самостоятельное балансированное дерево, которое сохраняет данные в отсортированном порядке после вставки, удаления и поиска. В общем, есть еще что изучать.