将参数传递到从C#中的dll检索的T4运行时模板

时间:2016-02-03 10:56:31

标签: c# dll t4

我有一个具有T4运行时模板的DLL和一个通过方法返回该模板实例的类(模板名称为Query.tt,它生成了Query.cs类):

来自dll的模板:

<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ template debug="true" #>
<#@ parameter name="TestObj" type="TemplateDLL.Class2" #>

Hellow <#= this.TestObj.s #>!
Hellow <#= this.TestObj.x #>!

来自dll的课程:

namespace TemplateDLL
{
   public class Class1
   {
       public Query getQueryTemplate()
       {
           return new Query();
       } 
   }
}

我正在使用Reflections:

将此dll加载到另一个项目中
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;

namespace TestDynTemplate2
{
    class Program
    {
        static void Main(string[] args)
        {
           var DLL = Assembly.LoadFile(@"D:\somedllpath\TemplateDLL.dll");

           dynamic c =  Activator.CreateInstance(DLL.GetType("TemplateDLL.Class1"));

           var templateInstance = c.getQueryTemplate();

           TemplateDLL.Class2 c2 = new TemplateDLL.Class2();
           c2.x = 3;
           c2.s = "cdfafdafa";


          templateInstance.Session = new Dictionary<string, object>();
          templateInstance.Session.Add("TestObj", c2);
          templateInstance.Initialize();

          var generatedCode = templateInstance.TransformText();

          Console.WriteLine(generatedCode);
        }
    }
}

我在两个项目中都有(在dll项目中和在dll调用项目中)我实例化的一个类(TemplateDLL.Class2)的定义(在调用dll项目中)并且我将实例传递给dll函数生成模板。我传递的对象用在dll中的模板中。

namespace TemplateDLL
{
    class Class2
    {
        public int x;
        public string s;
    }
}

一切正常,直到在模板中抛出System.InvalidCastException时在模板中使用该对象:[A] TemplateDLL.Class2无法强制转换为[B] TemplateDLL.Class2。并且它告诉我类型A和B的起源不一样。

如何使这项工作?我是c#和T4的新手。

1 个答案:

答案 0 :(得分:0)

在C#(以及一般的.NET)中,相同的定义并不意味着同一个类

在程序集A中声明的

Class2和程序集B中声明的Class2是完全不同的类(巧合地共享相同的名称空间和类名),因为类的全名和程序集都定义了它(其中还包括处理器体系结构和公钥,有关详细信息,请参阅GetType() on MSDN

您必须共享汇编,您可以将类型或副本(例如通过Reflection)从一种类型声明为另一种类型。像这样:

var instanceInBType = instanceInB.GetType();
foreach (var fieldInA in instanceFromA.GetType().GetFields())
{
    var fieldInB = instanceInBType.GetField(field.Name);
    var valueInA = fieldInA.GetValue(instanceFromA);

    fieldInB.SetValue(instanceInB, valueInA);
}

实际上,您必须接受通用 object参数(instanceFromA),创建局部变量instanceInB并按字段从A到B复制字段。当然,共享类型定义肯定更好......