6
Vote

WCSF 2.0's ProviderDependency doesn't work to get IPageFlowProvider

description

In WC-SF February 2008 the ObjectBuilder strategies were updated to improve the overall performance of the dependency injection mechanism. As part of this update, dynamic methods were introduced to reduce the use of reflection.
When the ProviderDependency attribute is applied to a property whose type is an interface, an exception is thrown because a dynamic method is being attached to an interface instead of a concrete class.
 
Technologies Affected
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
  • Web Client Software Factory Febreury 2008 (WCSF),
  • Page Flow Application Block (any version).
     
    Cause
    ¯¯¯¯¯¯¯
    When generating the IL for the ProviderDependency parameter resolution, the generated IL makes a call to the BuildUp method passing as the typeToBuild parameter the type of the decorated parameter/property. While executing the build plan, the DynamicMethodPlanBuilderPolicy.CreatePlan method tries to attach a DynamicMethod to the type passed to the BuildUp method. This fails when the type is an interface.
    EXAMPLE:
    private IPageFlowProvider _pageflowProvider;
     
    [ProviderDependency(typeof(PageFlowDirectory))]
    public IPageFlowProvider PageFlowProvider
    {
    get { return _pageflowProvider; }
    set { _pageflowProvider = value; }
    }
     
    Fix
    ¯¯¯
    The fix consists of modifying the IL generation in order to pass to the BuildUp method the concrete type of the object returned by the Provider property of the provider host instead of type of the decorated property.
     
    Steps
    ¯¯¯¯¯¯
  • Open the CompositeWeb solution.
  • Open the file located at: CompositeWeb\ObjectBuilder\BuildPlan\DynamicMethodPlan\Parameters\ProviderDependencyParameterResolver.cs
  • Find the EmitParameterResolution method and replace this line:
     
    Line 67: EmitLoadType(il, parameterType);
     
    ...with these lines:
     
    il.Emit(OpCodes.Ldloc, valueIndex);
    il.EmitCall(OpCodes.Callvirt, typeof(object).GetMethod("GetType", new Type[] {} ), null);
     
  • Save and build the solution.
  • Update the CompositeWeb assembly in your solution.
     
    Please, find attached the CompositeWeb assemblies and source code with the fix applied.
     
    Workarounds
    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    There are two possible workarounds:
    1 - Instead of using [ProviderDependency] attribute, use the "Provider" property from the host type (i.e. PageFlowDictionary) to get the instance of the provider.
    EXAMPLE:
    _pageflowProvider = PageFlowDictionary.Provider;
     
    2 - Change the property's type to the type of the expected concrete class of the provider.
    EXAMPLE:
    private IPageFlowProvider _pageflowProvider;
     
    [ProviderDependency(typeof(PageFlowDirectory))]
    public WorkflowFoundationPageFlowProvider PageFlowProvider
    {
    get { return (WorkflowFoundationPageFlowProvider)_pageflowProvider; }
    set { _pageflowProvider = value;
    }

file attachments

comments