VB.Net

How to sanitize a file name using LINQ

From this article you can learn how to sanitize a file name using simple LINQ query. SanitizeFilename function takes two parameters:
  • name - filename that needs to be sanitized
  • replaceChar - char used to replace all invalid file name characters
Implementation is available both in C# and VB.Net languages. Use buttons below to switch language visibility.

Implementation

System.Linq namespace needs to be put in usings.

public static string SanitizeFileName(string name, char replaceChar)
{
  return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
}
Public Shared Function SanitizeFileName(name As String, replaceChar As Char) As String
  Return Path.GetInvalidFileNameChars().Aggregate(name, Function(current, c) current.Replace(c, replaceChar))
End Function

How to resize description area in PropertyGrid


From this article you can learn how to resize description area in PropertyGrid. Example shows use of reflection in order to dig to private members of PropertyGrid - not accessible in normal way.

Implementation is available both in C# and VB.Net languages. Use buttons below to switch language visibility.

Implementation

System.Reflection namespace needs to be put in usings.

private static void ChangeDescriptionHeight(PropertyGrid grid, int height)
{
  if (grid == null) throw new ArgumentNullException("grid");
 
  foreach (Control control in grid.Controls)
   if (control.GetType().Name == "DocComment")
    {
      FieldInfo fieldInfo = control.GetType().BaseType.GetField("userSized",
        BindingFlags.Instance |
        BindingFlags.NonPublic);
      fieldInfo.SetValue(control, true);
      control.Height = height;
      return;
    }
}

Private Shared Sub ChangeDescriptionHeight(grid As PropertyGrid, height As Integer)
  If grid Is Nothing Then
    Throw New ArgumentNullException("grid")
  End If
 
  For Each control As Control In grid.Controls
    If control.[GetType]().Name = "DocComment" Then
      Dim fieldInfo As FieldInfo = control.[GetType]().BaseType.GetField("userSized", 
	    BindingFlags.Instance Or BindingFlags.NonPublic)
      fieldInfo.SetValue(control, True)
      control.Height = height
      Return
      End If
  Next
End Sub

Assembly custom attributes helper

From this article you can learn how to define and use simple helper. Example shows generic methods returning list of any type of Attribute from Assembly. AssemblyHelper class can be easily extended with further functionalities as needed.

Implementation and examples are available both in C# and VB.Net languages.

Implementation

Below you can find implementation we use in Karmian Framework as Assembly helper. All members in AssemblyHelper class should be marked as static, so no instance is needed to invoke any. Class AssemblyHelper itself is marked as sealed as we do not want to allow any inheritance. If you need to add new functionality that supports the Assembly - it should be implemented in the class AssemblyHelper. This approach allows the system to prevent duplication of helpers that are responsible for similar actions.

AssemblyHelper class

using System;
using System.Reflection;
 
namespace Karmian.Framework.Helpers
{
  public sealed class AssemblyHelper
  {
    public static T[] GetCustomAttributes<T>(Assembly assembly) where T : Attribute
    {
      return GetCustomAttributes<T>(assembly, true);
    }
 
    public static T[] GetCustomAttributes<T>(Assembly assembly, bool inherit) where T : Attribute
    {
      if (assembly == null)
        throw new ArgumentNullException("assembly");
      var attributes = assembly.GetCustomAttributes(typeof (T), inherit) as T[];
      return attributes ?? new T[0];
    }
  }
}

Imports System.Reflection
 
Namespace Karmian.Framework.Helpers
  Public NotInheritable Class AssemblyHelper
    Public Shared Function GetCustomAttributes(Of T As Attribute)(assembly As Assembly) As T()
      Return GetCustomAttributes(Of T)(assembly, True)
    End Function
 
    Public Shared Function GetCustomAttributes(Of T As Attribute)(assembly As Assembly, inherit As Boolean) As T()
      If assembly Is Nothing Then
        Throw New ArgumentNullException("assembly")
      End If
      Dim attributes = TryCast(assembly.GetCustomAttributes(GetType(T), inherit), T())
      Return If(attributes, New T(-1) {})
    End Function
  End Class
End Namespace

Enum description TypeConverter

From this article you can learn how to define and use enum description type converter so sytem will know how to handle enum to string and string to enum values (very helpful in PropertyGrid for example).

Implementation is available both in C# and VB.Net languages.

Implementation

Below you can find implementation we use in Karmian Framework as enum description type converter. It can be easily extended to work also as localizable enum description type converter - Description attribute can be used as a key of localized resource.

EnumDescriptionTypeConverter class

using System;
using System.ComponentModel;
using System.Globalization;
 
namespace Karmian.Core.TypeConverters
{
  public class EnumDescriptionTypeConverter : EnumConverter
  {
    public EnumDescriptionTypeConverter(Type type) : base(type)
    {
    }
 
    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
      return sourceType == typeof(string) || TypeDescriptor.GetConverter(typeof(Enum)).CanConvertFrom(context, sourceType);
    }
 
    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
      if (value is string)
        return GetEnumValue(EnumType, (string) value);
      if (value is Enum)
        return GetEnumDescription((Enum) value);
      return base.ConvertFrom(context, culture, value);
    }
 
    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
      return value is Enum && destinationType == typeof(string)
          ? GetEnumDescription((Enum)value)
          : (value is string && destinationType == typeof(string)
            ? GetEnumDescription(EnumType, (string)value)
            : base.ConvertTo(context, culture, value, destinationType));
    }
 
    public static string GetEnumDescription(Enum value)
    {
      var fieldInfo = value.GetType().GetField(value.ToString());
      var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
      return (attributes.Length > 0) ? attributes[0].Description : value.ToString();
    }
 
    public static string GetEnumDescription(Type value, string name)
    {
      var fieldInfo = value.GetField(name);
      var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
      return (attributes.Length > 0) ? attributes[0].Description : name;
    }
 
    public static object GetEnumValue(Type value, string description)
    {
      var fields = value.GetFields();
      foreach (var fieldInfo in fields)
      {
        var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
        if (attributes.Length > 0 && attributes[0].Description == description)
          return fieldInfo.GetValue(fieldInfo.Name);
        if (fieldInfo.Name == description)
          return fieldInfo.GetValue(fieldInfo.Name);
      }
      return description;
    }
  }
}

Imports System.ComponentModel
Imports System.Globalization
 
Namespace Karmian.Core.TypeConverters
  Public Class EnumDescriptionTypeConverter
    Inherits EnumConverter
    Public Sub New(type As Type)
      MyBase.New(type)
    End Sub
 
    Public Overrides Function CanConvertFrom(context As ITypeDescriptorContext, sourceType As Type) As Boolean
      Return sourceType Is GetType(String) OrElse TypeDescriptor.GetConverter(GetType([Enum])).CanConvertFrom(context, sourceType)
    End Function
 
    Public Overrides Function ConvertFrom(context As ITypeDescriptorContext, culture As CultureInfo, value As Object) As Object
      If TypeOf value Is String Then
        Return GetEnumValue(EnumType, DirectCast(value, String))
      End If
      If TypeOf value Is [Enum] Then
        Return GetEnumDescription(DirectCast(value, [Enum]))
      End If
      Return MyBase.ConvertFrom(context, culture, value)
    End Function
 
    Public Overrides Function ConvertTo(context As ITypeDescriptorContext, culture As CultureInfo, value As Object, destinationType As Type) As Object
      Return If(TypeOf value Is [Enum] AndAlso destinationType Is GetType(String), GetEnumDescription(DirectCast(value, [Enum])), (If(TypeOf value Is String AndAlso destinationType Is GetType(String), GetEnumDescription(EnumType, DirectCast(value, String)), MyBase.ConvertTo(context, culture, value, destinationType))))
    End Function
 
    Public Shared Function GetEnumDescription(value As [Enum]) As String
      Dim fieldInfo = value.[GetType]().GetField(value.ToString())
      Dim attributes = DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
      Return If((attributes.Length > 0), attributes(0).Description, value.ToString())
    End Function
 
    Public Shared Function GetEnumDescription(value As Type, name As String) As String
      Dim fieldInfo = value.GetField(name)
      Dim attributes = DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
      Return If((attributes.Length > 0), attributes(0).Description, name)
    End Function
 
    Public Shared Function GetEnumValue(value As Type, description As String) As Object
      Dim fields = value.GetFields()
      For Each fieldInfo As FieldInfo In fields
        Dim attributes = DirectCast(fieldInfo.GetCustomAttributes(GetType(DescriptionAttribute), False), DescriptionAttribute())
        If attributes.Length > 0 AndAlso attributes(0).Description = description Then
          Return fieldInfo.GetValue(fieldInfo.Name)
        End If
        If fieldInfo.Name = description Then
          Return fieldInfo.GetValue(fieldInfo.Name)
        End If
      Next
      Return description
    End Function
  End Class
End Namespace

Best Practices for Assembly Loading for portable applications

Some of you have certainly met with many different aspects of developing applications based on extensions. The following publication raises the question of practices for extensions in portable applications.

On msdn pages you will find well designed in theory and with almost identical title as ours: Best Practices for Assembly Loading . In short - we get a knowledge of the 'pros and cons' of different approaches and although unfortunately article lacks of practical examples it is worth to get familiar with it.
 

LINQ lambda expressions in universal generic equality comparer

Implementation

Below you can find implementation we use as universal equality comparer. Only lambda expressions as in LINQ queries are needed to measure items. Class LambdaComparer is generic, so you can use it on any type you want to.

LambdaComparer class

using System;
using System.Collections.Generic;
 
namespace Karmian.Framework.Helpers
{
    public class LambdaComparer<T> : IEqualityComparer<T>
    {
        public LambdaComparer(Func<T, T, bool> equals, Func<T, int> getHashCode)
        {
            _equals = equals;
            _getHashCode = getHashCode;
        }
 
        readonly Func<T, T, bool> _equals;
        public bool Equals(T x, T y)
        {
            return _equals(x, y);
        }
 
        readonly Func<T, int> _getHashCode;
        public int GetHashCode(T obj)
        {
            return _getHashCode(obj);
        }
    } 
}

Running executable from MemoryStream / Resources / binary array

Be aware, that executables or assemblies loaded in such manner share main application (host) domain. This implies that if there is any reference needed other from GAC (GlobalAssemblyCache) or host working directory - you will need to handle AppDomain.CurrentDomain.AssemblyResolve event or create new AppDomain for example. Sample code:
using System;
using System.IO;
using System.Reflection;
 
namespace ExecutableMemoryStream
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (args.Length == 0)
                    throw new TargetParameterCountException(
                             "Expected at least one parameter containing executable path.");
 
                using (FileStream fileStream = new FileStream(args[0], FileMode.Open))
                using (BinaryReader reader = new BinaryReader(fileStream))
                {
                    byte[] bin = reader.ReadBytes(Convert.ToInt32(fileStream.Length));
                    Assembly assembly = Assembly.Load(bin);
                    MethodInfo method = assembly.EntryPoint;
                    if (method != null)
                    {
                        object o = assembly.CreateInstance(method.ReflectedType.Name);
                        if (method.GetParameters().Length == 0)
                            method.Invoke(o, new object[0]);
                        else
                        {
                            string[] parameters = new string[args.Length - 1];
                            for (int i = 1; i < args.Length; i++)
                                parameters[i - 1] = args[i];
                            method.Invoke(o, new[] { parameters });
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.BackgroundColor = ConsoleColor.Red;
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine();
                Console.WriteLine(ex.Message.PadRight(80));
                Console.BackgroundColor = ConsoleColor.Black;
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Hit 'd' for details. Any other key will terminate application.");
                if (Console.ReadKey(true).KeyChar == 'd')
                {
                    Console.ForegroundColor = ConsoleColor.Gray;
                    Console.WriteLine();
                    Console.WriteLine(ex.StackTrace);
                    Console.ReadKey();
                }
            }
        }
    }
}
Syndicate content