将参数传递到从 C# 中的 dll 检索的 T4 运行时模板
Passing parameter into T4 runtime template retrieved from a dll in C#
我有一个 DLL,它有一个 T4 运行时模板和一个 class,它通过一个方法返回该模板的实例(模板名称是 Query.tt,它生成了 class 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 #>!
Class 来自 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);
}
}
}
我在两个项目(int dll 项目和 dll 调用项目)中也有一个 class (TemplateDLL.Class2) 的定义,我实例化了它(在调用 dll 中) project) 然后我将实例传递给生成模板的 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 中)相同的 定义 并不意味着 相同的 class。
Class2
在程序集 A 中声明的 Class2
和在程序集 B 中声明的 Class2
是完全不同的 classes(碰巧共享相同的命名空间和 class 名称)因为 class 由其全名和程序集定义(其中还包括处理器体系结构和 public 密钥,请参阅 GetType()
on MSDN 了解更多详细信息)。
您必须在声明该类型或从一种类型复制(例如通过反射)到另一种类型的地方共享程序集。像这样:
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);
}
实际上你必须接受一个 generic object
参数 (instanceFromA
),创建一个局部变量 instanceInB
并逐字段复制从A到B。当然共享类型定义肯定更好...
我有一个 DLL,它有一个 T4 运行时模板和一个 class,它通过一个方法返回该模板的实例(模板名称是 Query.tt,它生成了 class 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 #>!
Class 来自 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);
}
}
}
我在两个项目(int dll 项目和 dll 调用项目)中也有一个 class (TemplateDLL.Class2) 的定义,我实例化了它(在调用 dll 中) project) 然后我将实例传递给生成模板的 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 中)相同的 定义 并不意味着 相同的 class。
Class2
在程序集 A 中声明的 Class2
和在程序集 B 中声明的 Class2
是完全不同的 classes(碰巧共享相同的命名空间和 class 名称)因为 class 由其全名和程序集定义(其中还包括处理器体系结构和 public 密钥,请参阅 GetType()
on MSDN 了解更多详细信息)。
您必须在声明该类型或从一种类型复制(例如通过反射)到另一种类型的地方共享程序集。像这样:
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);
}
实际上你必须接受一个 generic object
参数 (instanceFromA
),创建一个局部变量 instanceInB
并逐字段复制从A到B。当然共享类型定义肯定更好...