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



我有一个 DLL,它有一个 T4 运行时模板和一个通过方法返回该模板实例的类(模板名称是 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();
       } 
   }
}

我正在使用反射将此 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:somedllpathTemplateDLL.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);
        }
    }
}

我还在两个项目(int 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 的新手。

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

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

您必须共享程序集,在其中声明该类型或将(例如通过反射)从一种类型复制到另一种类型。像这样:

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。当然,共享类型定义肯定更好...

最新更新