Development With A Dot

Blog on development in general, and specifically on .NET

  • Lesser-Known NHibernate Features: Future Queries

    Sometimes it makes sense to send several queries at the same time to the database server. This prevents multiple roundtrips and normally can provide results faster. Knowing this, NHibernate offers two features: multiqueries and future queries. Future queries build upon multiqueries and because they use LINQ, which is probably the most common querying API in NHibernate, I will focus in this.

    In order to use future queries, you queue them, by calling the ToFuture() or ToFutureValue() extension methods on any number of queries that you wish to retrieve together:

    1: var futureProducts = session.Query<Product>().Where(p => p.Price > 1000)

    .ToFuture();

       2:  
       3: var futureCustomers = session.Query<Customer>().Where(c => c.Orders.Any()).ToFuture();
       4:  
       5: //no query is sent to the database

    Only after you actually access its results are the queries sent:

       1: var productsCount = futureProducts.Count();

    And the generated SQL is:

       1: select
       2:     product0_.product_id as product1_6_,
       3:     product0_.name as name6_,
       4:     product0_.price as price6_
       5: from
       6:     product product0_
       7: where
       8:     product0_.price>@p0;
       9: select
      10:     customer0_.customer_id as customer1_3_,
      11:     customer0_.name as name3_,
      12:     customer0_.email as email3_
      13: from
      14:     customer customer0_
      15: where
      16:     exists (
      17:         select
      18:             orders1_.order_id
      19:         from
      20:             [
      21:         order] orders1_ where
      22:             customer0_.customer_id=orders1_.customer_id
      23:     );
      24: ;
      25: @p0 = 1000 [Type: Decimal (0)]

    Notice how the two queries are sent at the same time, separated by a semicolon.

    It also works for single values, they can be combined with multi value queries:

    1: var mostExpensiveFutureProduct = session.Query<Product>()

    .OrderByDescending(x => x.Price).Take(1).ToFutureValue();

    The caveat is that this, like multiqueries, is right now only supported in SQL Server, Oracle and MySQL. In all the other cases the results will be retrieved immediately.





    Read more...

  • Unity - Part 7: Adding Interfaces

    Another post on the Unity series, this time, adding interfaces to proxies. Previous posts here (Registration by Convention), here (Injecting Values), here (Extensions), here (Aspect-Oriented Programming), here (Dependency Injection) and here (Introduction).

    Unity can be used to inject additional interfaces to proxies generated for some type. We can easily add these interfaces at registration time but then we need to implement a behavior that can intercept calls to these interfaces and act accordingly.

    A typical example is implementing INotifyPropertyChanged. Let’s see how we can register a type with this additional interface, first, by XML:

       1: <register type="MyNamespace.IMyInterface" mapTo="MyNamespace.MyClass">
       2:     <addInterface type="System.ComponnetModel.INotifyPropertyChanged"/>
       3: </register>

    And by code:

       1: unity.RegisterType<IMyInterface, MyClass>(new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<NotifyPropertyChangedInterceptionBehavior>(), new AdditionalInterface<INotifyPropertyChanged>() });

    Do note that I am explicitly setting the interceptor as InterfaceInterceptor, other ways exist, see part 3 of this series.

    Now, let’s see the NotifyPropertyChangedBehavior class:

       1: public class NotifyPropertyChangedInterceptionBehavior : IInterceptionBehavior
       2: {
       3:     private event PropertyChangedEventHandler handlers = delegate { };
       4:  
       5:     #region IInterceptionBehavior Members
       6:  
       7:     public IEnumerable<Type> GetRequiredInterfaces()
       8:     {
       9:         yield return (typeof(INotifyPropertyChanged));
      10:     }
      11:  
      12:     public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
      13:     {
      14:         var result = null as IMethodReturn;
      15:  
      16:         if (input.MethodBase.IsSpecialName == true)
      17:         {
      18:             if (input.MethodBase.Name.StartsWith("set_") == true)
      19:             {
      20:                 result = getNext()(input, getNext);
      21:  
      22:                 this.handlers(input.Target, new PropertyChangedEventArgs(input.MethodBase.Name.Substring(4)));
      23:             }
      24:             else if (input.MethodBase.Name == "add_PropertyChanged")
      25:             {
      26:                 this.handlers += (input.Arguments[0] as PropertyChangedEventHandler);
      27:  
      28:                 result = input.CreateMethodReturn(null, input.Arguments);
      29:             }
      30:             else if (input.MethodBase.Name == "remove_PropertyChanged")
      31:             {
      32:                 this.handlers -= (input.Arguments[0] as PropertyChangedEventHandler);
      33:  
      34:                 result = input.CreateMethodReturn(null, input.Arguments);
      35:             }
      36:         }
      37:  
      38:         return (result);
      39:     }
      40:  
      41:     public Boolean WillExecute
      42:     {
      43:         get { return(true); }
      44:     }
      45:  
      46:     #endregion
      47: }

    Finally, sample usage:

       1: var component = unity.Resolve<IMyInterface>();
       2: var npc = component as INotifyPropertyChanged;
       3:  
       4: npc.PropertyChanged += delegate(Object source, PropertyChangedEventArgs args)
       5: {
       6:     //raised with args.PropertyName = MyProperty
       7: };
       8:  
       9: component.MyProperty = "Some Value";  //raises PropertyChanged event

    Still lots of things to talk about Unity, stay tuned for more! Winking smile

    Read more...

  • Applying Code Access Restrictions in .NET

    Sometimes there is the need or desire to resort to Aspect-Oriented frameworks (AOP) in order to add some validations or cross-cutting concerns. In several situations, it is indeed necessary, but .NET already offers some hooks that we can use to achieve parts of this functionality. One of those is CodeAccessSecurityAttribute. In a nutshell, it allows the application of security checks whenever some code – method, property – is called. A somewhat well known example is PrincipalPermissionAttribute.

    Let’s see an example of how we can restrict a method so that it can only be called on a specific day of the week:

       1: [Serializable]
       2: public sealed class DayOfWeekPermission : IPermission
       3: {
       4:     public DayOfWeek AllowedDayOfWeek { get; private set; }
       5:  
       6:     public DayOfWeekPermission(DayOfWeek allowedDayOfWeek)
       7:     {
       8:         this.AllowedDayOfWeek = allowedDayOfWeek;
       9:     }
      10:  
      11:     #region IPermission Members
      12:  
      13:     public IPermission Copy()
      14:     {
      15:         return(new DayOfWeekPermission(this.AllowedDayOfWeek));
      16:     }
      17:  
      18:     public void Demand()
      19:     {
      20:         new SecurityPermission(SecurityPermissionFlag.ControlPrincipal).Assert();
      21:  
      22:         if (this.AllowedDayOfWeek != DateTime.Today.DayOfWeek)
      23:         {
      24:             throw (new SecurityException("Cannot run on the current day of week") { Action = SecurityAction.Demand, FirstPermissionThatFailed = this, DenySetInstance = this });
      25:         }
      26:     }
      27:  
      28:     public IPermission Intersect(IPermission target)
      29:     {
      30:         return (null);
      31:     }
      32:  
      33:     public Boolean IsSubsetOf(IPermission target)
      34:     {
      35:         return (false);
      36:     }
      37:  
      38:     public IPermission Union(IPermission target)
      39:     {
      40:         return (this);
      41:     }
      42:  
      43:     #endregion
      44:  
      45:     #region ISecurityEncodable Members
      46:  
      47:     public void FromXml(SecurityElement e)
      48:     {
      49:         if (e.Tag == "AllowedDayOfWeek")
      50:         {
      51:             this.AllowedDayOfWeek = (DayOfWeek) Enum.Parse(typeof(DayOfWeek), e.Text, true);
      52:         }
      53:     }
      54:  
      55:     public SecurityElement ToXml()
      56:     {
      57:         return (new SecurityElement("AllowedDayOfWeek", this.AllowedDayOfWeek.ToString()));
      58:     }
      59:  
      60:     #endregion
      61: }
      62:  
      63: [Serializable]
      64: [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
      65: public sealed class DayOfWeekPermissionAttribute : CodeAccessSecurityAttribute
      66: {
      67:     public DayOfWeek AllowedDayOfWeek { get; set; }
      68:  
      69:     public DayOfWeekPermissionAttribute(SecurityAction action) : base(action)
      70:     {
      71:     }
      72:  
      73:     public override IPermission CreatePermission()
      74:     {
      75:         return (new DayOfWeekPermission((this.AllowedDayOfWeek)));
      76:     }
      77:  
      78:     public override Boolean Equals(Object obj)
      79:     {
      80:         var dowp = obj as DayOfWeekPermissionAttribute;
      81:  
      82:         if (dowp == null)
      83:         {
      84:             return (false);
      85:         }
      86:  
      87:         return (dowp.AllowedDayOfWeek == this.AllowedDayOfWeek);
      88:     }
      89:  
      90:     public override Int32 GetHashCode()
      91:     {
      92:         return (this.AllowedDayOfWeek.GetHashCode());
      93:     }
      94: }

    The Intersect, Union and IsSubsetOf methods really don’t apply in this simple case, but the Demand method does: this is where the actual logic goes. The example should be pretty straightforward. One thing to keep in mind, though: classes inheriting from CodeAccessSecurityAttribute should expose a public constructor with a single SecurityAction parameter, otherwise, it won’t be called.

    The attribute can be applied as:

       1: [DayOfWeekPermission(SecurityAction.Demand, AllowedDayOfWeek = DayOfWeek.Monday)]
       2: public void MethodToRunOnMondays()
       3: {
       4:     //if today is not Monday, an exception is thrown
       5: }

    But this technique can be used for things other than permission checks. Let’s see logging applied to a class:

       1: [Serializable]
       2: [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
       3: public sealed class LogPermissionAttribute : CodeAccessSecurityAttribute
       4: {
       5:     public LogPermissionAttribute(SecurityAction action) : base(action)
       6:     {
       7:     }
       8:  
       9:     public override IPermission CreatePermission()
      10:     {
      11:         return (new LogPermission());
      12:     }
      13:  
      14:     public override Boolean Equals(Object obj)
      15:     {
      16:         return (obj is LogPermissionAttribute);
      17:     }
      18:  
      19:     public override Int32 GetHashCode()
      20:     {
      21:         return (base.GetHashCode());
      22:     }
      23: }
      24:  
      25: [Serializable]
      26: public sealed class LogPermission : IPermission
      27: {
      28:  
      29:     #region IPermission Members
      30:  
      31:     public IPermission Copy()
      32:     {
      33:         return (new LogPermission());
      34:     }
      35:  
      36:     public void Demand()
      37:     {
      38:         var stackTrace = new StackTrace();
      39:         var frames = stackTrace.GetFrames().Skip(2);
      40:         var callingMethod = frames.First().GetMethod();
      41:         System.Console.WriteLine("Calling method {0}", callingMethod);
      42:     }
      43:  
      44:     public IPermission Intersect(IPermission target)
      45:     {
      46:         return (null);
      47:     }
      48:  
      49:     public Boolean IsSubsetOf(IPermission target)
      50:     {
      51:         return (false);
      52:     }
      53:  
      54:     public IPermission Union(IPermission target)
      55:     {
      56:         return (this);
      57:     }
      58:  
      59:     #endregion
      60:  
      61:     #region ISecurityEncodable Members
      62:  
      63:     public void FromXml(SecurityElement e)
      64:     {
      65:     }
      66:  
      67:     public SecurityElement ToXml()
      68:     {
      69:         return (new SecurityElement("LogPermission", String.Empty));
      70:     }
      71:  
      72:     #endregion
      73: }

    Yes, I know… it really has no access to method parameters, and it really doesn’t anything really productive, it’s just an example, remember! Winking smile

    An example of its usage:

       1: [LogPermission(SecurityAction.Demand)]
       2: public class MyClass
       3: {
       4:     //all method calls will be logged
       5: }

    If you have other usages, please send them to me, I’ll make sure to refer where they came from! Smile

    Read more...

  • Lesser-Known NHibernate Features: Entity Mode Map

    This one is a real treat!

    When we use NHibernate or any other O/RM, we normally use classes to represent the database objects (tables or views). In NHibernate, this is called Entity Mode POCOPlain Old CLR Object. NHibernate, however, supports other Entity Mode: Map. This Entity Mode does not use “physical” classes, but instead, dictionaries (implementations of IDictionary)! This makes it great for mapping dynamic database objects without the need for real classes.

    For creating a Map entity, we need to do a slight change in our usual mappings, here is a simple Parent-Child example:

       1: <?xml version="1.0" encoding="utf-8" ?>
       2: <hibernate-mapping namespace="Succinctly.Model" assembly="Succinctly.Model" xmlns="urn:nhibernate-mapping-2.2">
       3:     <class entity-name="Parent" table="`PARENT`">
       4:         <id name="Name" column="`NAME`" type="String" length="50" generator="assigned"/>
       5:         <set name="Children" lazy="true" inverse="true" cascade="all-delete-orphan">
       6:             <key column="`PARENT_NAME`" not-null="true"/>
       7:             <one-to-many entity-name="Child"/>
       8:         </set>
       9:     </class>
      10:     <class entity-name="Child" table="`CHILD`">
      11:         <id name="Name" column="`NAME`" type="String" length="50" generator="assigned"/>
      12:         <many-to-one name="Parent" entity-name="Parent" column="`PARENT_NAME`" not-null="true"/>
      13:     </class>
      14: </hibernate-mapping>

    You might not have noticed that I used entity-name instead of name in the <class> declaration, in <one-to-many> and <many-to-one>; this tells NHibernate that these classes will be mapped as Map, not POCO (the default). Alas, you cannot use mapping by code, because there is no physical class to map.

    OK, so now we have a mapped Parent and Child. We insert them as this:

       1: using (var session = sessionFactory.OpenSession())
       2: {
       3:     var parent = new Hashtable { { "Name", "Parent Name" } };
       4:     parent["Children"] = new HashSet<Object> { new Hashtable { { "Name", "Child Name" }, { "Parent", parent } } };
       5:  
       6:     session.Save("Parent", parent);
       7:     session.Flush();
       8: }

    I am using Hashtable as an IDictionary implementation, but you might as well use Dictionary<TKey, TValue>. It doesn’t really matter.

    As for retrieving, also simple, just use the ISession methods that take an entityName parameter:

       1: var parentProxy = session.Load("Parent", "Parent Name") as IDictionary;
       2:  
       3: var parent = session.Get("Parent", "Parent Name") as IDictionary;

    Each of these IDictionary instances will have an entry that has key “$type$” and contains the entity type name – in our case, either “Parent” or “Child” – as well as entries for each of the other mapped properties, associations and collections:

       1: var name = parent["Name"] as String;
       2: var children = parent["Children"] as ISet<Object>;

    Entity Mode Map supports both HQL and Criteria querying APIs:

       1: var parentsByCriteria = session.CreateCriteria("Parent").Add(Restrictions.Eq("Name", "Parent Name")).List();
       2:  
       3: var parentsByHQL = session.CreateQuery("from Parent where Name = :name").SetParameter("name", "Parent Name").List();

    And it also supports executable HQL:

       1: session.CreateQuery("delete from Child").ExecuteUpdate();

    Cool, don’t you thing? Eat your heart out, Unnamed Framework! Winking smile

    Read more...

  • Conditional Content in SharePoint Markup

    In SharePoint, there are several web parts that allow us to have different contents depending on some conditions:

    I imagine you are now rolling your eyes: DataViewWebPart? how come? Well, because it doesn’t need to point to a specific list or view (unlike XsltListViewWebPart), it is very useful for markup-based customizations that will only depend on parameters.

    Let’s see an example:

       1: <WebPartPages:DataFormWebPart runat="server" Title="Conditional Content">
       2:     <ParameterBindings>
       3:         <ParameterBinding Name="MyParameter" Location="QueryString(MyParameter)"/>
       4:     </ParameterBindings>
       5:     <XSL>
       6:         <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl asp" xmlns:asp="System.Web.UI.WebControls">                                                  
       7:             <xsl:param name="MyParameter"/>                                                                                                                                        
       8:             <xsl:template match="/">
       9:                 <asp:Label runat="server" Text="Some content, just to show ASP.NET controls inside a SharePoint DataFormWebPart"/>
      10:                 <xsl:choose>
      11:                     <xsl:when test="$MyParameter=''">
      12:                         No parameter...
      13:                     </xsl:when>
      14:                     <xsl:otherwise>
      15:                         Allright! <xsl:value-of select="$MyParameter"/>
      16:                     </xsl:otherwise>
      17:                 </xsl:choose>                                                                                                
      18:             </xsl:template>
      19:         </xsl:stylesheet>
      20:     </XSL>                                        
      21: </WebPartPages:DataFormWebPart>

    You can use this technique for:

    • Including scripts and stylesheets;
    • Including server-side controls.

    It’s just a matter of rolling out some XSL to the rescue!

    You may be already familiar with the available parameters, but you can find the full list here: http://msdn.microsoft.com/en-us/library/office/ff630170(v=office.15).aspx.

    Another SharePoint Designer-only solution that may come in handy! ;-)

    Read more...

  • Lesser-Known NHibernate Features: Mixing Client and Server-Side Calls in Projections

    Another not widely known feature of NHibernate: mixing client and server-side calls.

    To illustrate this, imagine that you want to calculate the difference between a mapped DateTime property and the current time, DateTime.Now. The following query works in NHibernate, but not in other O/RM frameworks:

       1: var timespans = session.Query<Order>().Select(x => DateTime.Now - x.Date).ToList();

    The generated SQL will only be:

       1: select
       2:     order0_.[date] as col_0_0_
       3: from
       4:     [
       5: order] order0_

    But NHibernate will detect that the result needs to be combined with something from the client side and will return a TimeSpan. This mechanism is extensible – more on this in a future post.

    In other O/RMs, which shall remain unnamed, you have to use LINQ to Objects after LINQ to Unnamed Framework:

       1: ctx.Orders.Select(x => new { ElapsedTime = SqlFunctions.DateDiff("HOUR", x.Date, DateTime.Now) }).ToList().Select(x => TimeSpan.FromHours(x.EllapsedTime));

    Pretty cool, don’t you think? Winking smile

    Read more...

  • Lesser-Known NHibernate Features: Mapping a Class to a Query

    Today I start a new series on lesser-known NHibernate features.

    Besides the normal mapping of a class to a table (or view, for that matter), it is also possible to map a class to a query. Do note that this is not the same as having a class mapped to a table and using custom SQL for the INSERTs, UPDATEs, SELECTs or DELETEs, this is something different. This is called Subselect mapping - not to be confused with subselect fetching.

    To demonstrate this, imagine we have a blogging model where a Blog has several Posts. We can map a readonly query between the two as (in HBM.XML):

       1: <?xml version="1.0" encoding="utf-8"?>
       2: <hibernate-mapping namespace="Succinctly.Model" assembly="Succinctly.Model" xmlns="urn:nhibernate-mapping-2.2">
       3:     <class name="BlogPost" mutable="false">
       4:         <subselect>
       5:             <![CDATA[
       6:             SELECT blog_id, (SELECT COUNT(1) FROM post WHERE post.blog_id = blog.blog_id) post_count FROM blog
       7:             ]]>
       8:         </subselect>
       9:         <synchronize table="blog"/>
      10:         <synchronize table="post"/>
      11:         <id column="blog_id" name="BlogId"/>
      12:         <property name="PostCount" column="post_count"/>
      13:     </class>
      14: </hibernate-mapping>

    In mapping by code, it would be:

       1: public class BlogPostMapping : ClassMapping<BlogPost>
       2: {
       3:     public BlogPostMapping()
       4:     {
       5:         this.Subselect("SELECT blog_id, (SELECT COUNT(1) FROM post WHERE post.blog_id = blog.blog_id) post_count FROM blog");
       6:         this.Mutable(false);
       7:         this.Synchronize("blog", "post");
       8:         this.Id(x => x.BlogId, x => x.Column("blog_id"));
       9:         this.Property(x => x.PostCount, x => x.Column("post_count"));
      10:     }
      11: }

    It easy to understand that the class cannot be mutable: it makes no sense to change any of the properties, because they may not map directly to a table.

    Querying is done in exactly the same way:

       1: session.Query<BlogPost>().ToList();

    And the resulting SQL is:

       1: select
       2:     blogpost0_.blog_id as blog1_19_,
       3:     blogpost0_.post_count as post2_19_
       4: from
       5:     ( SELECT
       6:         blog_id,
       7:         (SELECT
       8:             COUNT(1)
       9:         FROM
      10:             post
      11:         WHERE
      12:             post.blog_id = blog.blog_id) post_count
      13:     FROM
      14:         blog ) blogpost0_

    Read more...

  • Nesting SPDataSource Controls

    Sometimes, when you are using a SPDataSource control to bind to some list control, you might need, inside of it, to fetch information from the item you are iterating over.

    Imagine, for example, that you are displaying a list of sites. As usual with SharePoint, there are lots of options for doing this, but consider the SPDataSource approach, which doesn’t require any coding:

       1: <SharePoint:SPDataSource runat="server" DataSourceMode="Webs" ID="subsites">
       2:     <SelectParameters>
       3:         <asp:Parameter Name="WebID" DefaultValue="RootWeb"/>
       4:     </SelectParameters>
       5: </SharePoint:SPDataSource>
       6:  
       7: <asp:Repeater runat="server" ID="list" DataSourceID="subsites">
       8:     <ItemTemplate>
       9:         <!-- show an hyperlink to the subsite and its title -->
      10:         <asp:HyperLink runat="server" ID="titleLink" Text='<%# Eval("__spTitle") %>' NavigateUrl='<%# Eval("__spDefaultUrl") %>'/>
      11:     </ItemTemplate>
      12: </asp:Repeater>

    This is using DataSourceMode=Webs, which, together with parameter RootWeb, displays all subsites under the root site. I’m using a Repeater to display data, but you can use whatever you want.

    But now you want to display all lists of each subsite… What would you do then?

    OK, we need to get, for each site listed, its id, and store it in some server-side control, such as HiddenField. Next, we add a nested SPDataSource, this time with DataSourceMode=ListOfLists, and add a WebID parameter:

       1: <ItemTemplate>
       2:     <asp:HiddenField runat="server" ID="webid" Value='<%# Eval("__spID") %>'/>
       3:     <SharePoint:SPDataSource runat="server" DataSourceMode="ListOfLists" ID="lists">
       4:         <SelectParameters>
       5:             <asp:ControlParameter Name="WebID" ControlID="webid"/>
       6:         </SelectParameters>                            
       7:     </SharePoint:SPDataSource>
       8: ...
       9: </ItemTemplate>

    Now, all you need is to bind some control, like a Repeater, to the nested SPDataSource. Here is the final code:

       1: <asp:Repeater runat="server" ID="list" DataSourceID="subsites">
       2:     <ItemTemplate>
       3:         <asp:HiddenField runat="server" ID="webid" Value='<%# Eval("__spID") %>'/>
       4:         <SharePoint:SPDataSource runat="server" DataSourceMode="ListOfLists" ID="lists">
       5:             <SelectParameters>
       6:                 <asp:ControlParameter Name="WebID" ControlID="webid"/>
       7:             </SelectParameters>                            
       8:         </SharePoint:SPDataSource>
       9:         
      10:         <asp:Repeater runat="server" DataSourceID="lists">
      11:             <ItemTemplate>
      12:                 <p><asp:Literal runat="server" ID="l" Text='<%# Eval("__spTitle") %>'/></p>
      13:             </ItemTemplate>
      14:         </asp:Repeater>
      15:         <div class="area-item">
      16:             <asp:HyperLink runat="server" ID="titleLink" Text='<%# Eval("__spTitle") %>' NavigateUrl='<%# Eval("__spDefaultUrl") %>'/>
      17:         </div>                            
      18:     </ItemTemplate>                    
      19: </asp:Repeater>

    If you are curious, the MSDN page SPDataSource.SelectParameters lists all predefined parameters that the SPDataSource will recognize automatically, and this page in Solutionizing .NET lists all fields returned by SPDataSource, in all of its modes. BTW, a great resource! Winking smile

    If you want to improve things a bit, you might want to set the filter query on the nested SPDataSource’s SelectCommand property. I leave that as an exercise to you, dear reader! Winking smile










    Read more...

  • Type Conversions in .NET

    Sometimes we have an instance of some class that is not exactly the one we want. This can either be because it is not typed – is of type Object – or for some other reason. When that happens, we need to convert it.

    There are several ways that the .NET allows for doing more or less automated conversions between types. I usually use the following function, which does this:

    1. Matching type: if the destination type can be assigned from the source value type;
    2. Destination type String: this is pretty obvious, just call ToString() on the source value;
    3. IConvertible implementations: if both types implement IConvertible – normally only base types do –, then we can call Convert.ChangeType method;
    4. Destination type TypeConverter: if the destination type provides a type converter, normally by a TypeConverterAttribute, and this type converter allows converting from the source, then use it for the conversion;
    5. Source type TypeConverter: if the source value provides a type converter and it can convert to the destination type, then use it;
    6. Implicit and explicit conversion operators: if the source value has implicit or explicit conversion operators for the destination type, use them.

    The code looks like this:

       1: public static Object Convert(Object value, Type destinationType)
       2: {
       3:     //if value is null, nothing we can do
       4:     if (value == null)
       5:     {
       6:         return (null);
       7:     }
       8:  
       9:     //if no destination type is supplied, just return the source object
      10:     if (destinationType == null)
      11:     {
      12:         return (value);
      13:     }
      14:  
      15:     //if types are compatible, return the source object
      16:     if (destinationType.IsInstanceOfType(value) == true)
      17:     {
      18:         return (value);
      19:     }
      20:  
      21:     //if the destination type is string, just call ToString()
      22:     if (destinationType == typeof(String))
      23:     {
      24:         return (value.ToString());
      25:     }
      26:  
      27:     //if both types are IConvertible, call ChangeType()
      28:     if ((typeof(IConvertible).IsAssignableFrom(destinationType) == true) && (typeof(IConvertible).IsAssignableFrom(value.GetType()) == true))
      29:     {
      30:         return (System.Convert.ChangeType(value, destinationType));
      31:     }
      32:  
      33:     //if the destination type has a type converter that can handle the source object, use it
      34:     var converter = TypeDescriptor.GetConverter(destinationType);
      35:  
      36:     if ((converter != null) && (converter.CanConvertFrom(value.GetType()) == true))
      37:     {
      38:         return (converter.ConvertFrom(value));
      39:     }
      40:  
      41:     converter = TypeDescriptor.GetConverter(value.GetType());
      42:  
      43:     //if the source value has a type converter that can handle the destination type, use it
      44:     if ((converter != null) && (converter.CanConvertTo(destinationType) == true))
      45:     {
      46:         return (converter.ConvertTo(value, destinationType));
      47:     }
      48:  
      49:     //check if the type has an explicit conversion operator and use it
      50:     var conversionOperator = value.GetType().GetMethod("op_Explicit", BindingFlags.Static | BindingFlags.Public);
      51:  
      52:     if ((conversionOperator.ReturnType == destinationType) && (conversionOperator.GetParameters().Length == 1) && (conversionOperator.GetParameters()[0].ParameterType.IsAssignableFrom(value.GetType()) == true))
      53:     {
      54:         return (conversionOperator.Invoke(null, new Object[] { value }));
      55:     }
      56:  
      57:     //check if the type has an implicit conversion operator and use it
      58:     conversionOperator = value.GetType().GetMethod("op_Implicit", BindingFlags.Static | BindingFlags.Public);
      59:  
      60:     if ((conversionOperator.ReturnType == destinationType) && (conversionOperator.GetParameters().Length == 1) && (conversionOperator.GetParameters()[0].ParameterType.IsAssignableFrom(value.GetType()) == true))
      61:     {
      62:         return (conversionOperator.Invoke(null, new Object[] { value }));
      63:     }
      64:  
      65:     //maybe throw an exception instead?
      66:     return (null);
      67: }

    So, am I missing anything? Do let me know! Winking smile

    Read more...