locked
DynamicTypeService in T4 template RRS feed

  • Question

  • Has anyone found a way to get access to DynamicTypeService from within a T4 template in VS2012?  All the code posted online and in the forums always has the same solution of using GetService() to retrieve the object.  In VS2012 that doesn't work.  The problem is that DTS is an abstract class, not an interface.  The object that you'll get back is a COM object.  Hence when you try to cast it you'll get the popular "Unable to cast a System._ComObject..." error.  The error is correct because DTS does not implement any interfaces and therefore QI won't work.  Yet there has to be some way of getting to this type so we can do type resolution.  I'm wondering if it broken when they resolved the issue of T4 locking assemblies.  Thoughts?

    I'm looking into doing it the hard way using the Project to get the assemblies and types but that is sort of what DTS does so it doesn't make sense.

    Michael Taylor - 1/18/2013
    http://msmvps.com/blogs/p3net

    Friday, January 18, 2013 7:29 PM

All replies

  • Hi,

    Thank you for posting in the MSDN Forum.
     
    I will involve some experts into this issue to see whether they can help you out. There might be some time delay, appreciate for your patience.
     
    Thank you for your understanding and support.
     
    Best regards,

    Ego [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, January 21, 2013 8:11 AM
  • Hi Michael,

    I am checking with our Products Group to get some pointers on this.

    Thanks,

    Gaurav

    Friday, February 15, 2013 10:28 PM
  • That would be great.  For now I've had to resort to walking the project references and then, using hueristics, load the assembly using LoadFrom.  Since the T4 is loaded in a temp app domain this works but there are lots of issues with it:

    1) Would prefer to use the reflection only context but then custom attributes don't work without using the alternate custom attribute lookup types.

    2) Project references don't work at all since they might not even be compiled yet.  Mixing code models and reflection-based types isn't ideal.

    3) Service references (which is where I really needed this functionality) don't work because the type definitions are in the project I'm trying to resolve from.

    For now I'm accepting this limitation but I'd really like to get DTS working again.

    Friday, February 15, 2013 10:45 PM
  • Hi Matt,

    I got the same suggestion of using GetService().

    For example, this should work:

    Var _dyanmicTypeService = serviceProvider.GetService(typeof(DynamicTypeService)) as DynamicTypeService;

    If above does not work, Can you have a sample repro for me so that I can demonstrate it to our PG?

    Thanks,

    Gaurav



    Friday, February 15, 2013 11:02 PM
  • Here's a snippet of T4 code that I've tried.

    <#@ template debug="false" hostspecific="true" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ assembly name="EnvDTE" #>
    <#@ assembly name="Microsoft.VisualStudio.Shell.Design" #>
    <#@ assembly name="Microsoft.VisualStudio.OLE.Interop" #>
    <#@ assembly name="Microsoft.VisualStudio.Shell.11.0" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="Microsoft.VisualStudio.Shell" #>
    <#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #>
    <#@ import namespace="Microsoft.VisualStudio.OLE.Interop" #>
    <#@ output extension=".txt" #>
    <#
        //Use host IServiceProvider
        var hostServiceProvider = Host as System.IServiceProvider;
        if (hostServiceProvider == null) throw new Exception("Host service provider failed");
        
        //Get an error saying the type is not marked as serializable
        var hostDts = hostServiceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Design.DynamicTypeService)) as Microsoft.VisualStudio.Shell.Design.DynamicTypeService;
        if (hostDts == null) throw new Exception("No host DTS");
    
        //Use DTE IServiceProvider
        var dte = hostServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
        if (dte == null) throw new Exception("Unable to get DTE");
    
        var dteServiceProvider = new Microsoft.VisualStudio.Shell.ServiceProvider(dte as Microsoft.VisualStudio.OLE.Interop.IServiceProvider);
        if (dteServiceProvider == null) throw new Exception("No service provider");
            
        var dteDts = dteServiceProvider.GetService(typeof(Microsoft.VisualStudio.Shell.Design.DynamicTypeService)) as Microsoft.VisualStudio.Shell.Design.DynamicTypeService;
        if (dteDts == null) throw new Exception("No DTE DTS");
    #>

    In the first set of code I'm using Host and it generates an error saying DTS isn't serializable.  In the second set of code I try to use DTE and it fails.  In the actual T4 template I was trying to use I rely on T4 Toolbox and it was failing with the COM object error I started this thread with.

    Michael Taylor - 2/16/2013
    http://msmvps.com/blogs/p3net

    Saturday, February 16, 2013 8:39 PM
  • Hi Michael,

    After discussing this with our PM's, it looks like this might not be possible. There is no supported way to get this done. You can try something like, creating new instance by reflection for INTERNAL class VSDynamicTypeService in your template, which is the concrete class. But, again thats not supported way of doing. Sorry, looks like you are out of luck here.

    Thanks,

    Gaurav

    Wednesday, February 27, 2013 4:59 PM