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