在众多.NET应用下的代码生成方案中,比如CodeDOMBuildProvider, 我觉得T4是最好的一种。关于T4的基本概念和模板结果,可以参考我的文章《基于T4的代码生成方式》。如果要了解T4具体的应用,则可以参考我的文章《创建代码生成器可以很简单:如何通过T4模板生成代码?》(上篇)(下篇)。如果你编写T4模板,你不得不面对一个问题——如何引用一个程序集?VS 2010采用了与VS2008不同的程序集引用的解析机制。本篇文章为你介绍在VS2010下5种不同的程序集引用的方式。

目录 
一、添加程序集引用解决不了问题 
二、将引用程序集安装到GAC 
三、利用VS的PublicAssemblies目录 
四、指定程序集的具体路径 
五、采用环境变量 
六、使用VS宏

一、添加程序集引用解决不了问题

如果你的T4模板需要调用一个自定义的类型,并且该类型定义在某个非系统程序集中,你就需要通过T4<#@ assembly…#>指令引用该程序集。在VS 2008环境下,你只需要为当前项目添加相应的程序集引用,并且通过<@ assembly…#>指令的name属性指定程序集(Dll)的文件名即可。比如,下面的T4模板包含了对程序集Artech.T4AssemblyRefResovle.Foo.dll的引用。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

但是这种方式对于VS 2010则行不通,因为T4引擎在解析和编译模板的时候并不会从项目引用列表中去定位目标程序集。所以,对于上面的T4模板,会出现如下的编译错误。

二、将引用程序集安装到GAC

其实我们有很多方式来解决这个问题,你首先想到的肯定是将引用的程序集安装到GAC中。没错,这是一种解决方案,如果被引用的程序集具有强签名的话。有一点需要注意的是,T4模板引用某个安装于GAC的程序集的时候,在<#@ assembly…#>指令下不能指定文件扩展名(.dll)。T4模板应该按照如下的方式定义。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

三、利用VS的PublicAssemblies目录

为了让T4引擎能够找到引用的程序集,你可以将其拷贝到VS 2010的PublicAssemblies目的下,该目录为C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies。如果将Artech.T4AssemblyRefResovle.Foo.dll拷贝到该目录下,你在T4模板的<#@ assembly…#>指令下就可以直接指定程序集名称(不包括扩展名)或者程序集文件名(包括扩展名)。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

指定文件扩展名

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

四、指定程序集的具体路径

如果被引用的程序集被没有被签名,GAC的方式则不能使用,在这种情况下你需要指定程序集文件所在的位置,最直接的当然就是指定程序集文件的绝对路径。在下面的T4模板中,<#@ assembly…#>指令中指定的就是Artech.T4AssemblyRefResovle.Foo.dll文件的绝对路径。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="D:\T4AssemblyRefResovle\Lib\Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

五、采用环境变量

采用程序集文件的绝对路径这种硬编码并不是一种推荐的解决方案,因为在团队开发中,每个开发人员用于存放同一个程序集的地址可能不同,在这种情况下你可以采用环境变量的方式。你可以定义个环境变量(比如FooDir)表示本机用于保存程序集的目录(比如D:\T4AssemblyRefResovle\Lib),那么被引用的程序集就可以表示成:%FooDir%\Artech.T4AssemblyRefResovle.Foo.dll.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="%FooDir%\Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

六、使用VS宏

如果被引用的程序集所在目录是在当前解决方案或者当前项目的子目录(这是一种很常见的公共程序集保存方式),你还可以通过VS的宏命令来指定该目录。比如我们的Artech.T4AssemblyRefResovle.Foo.dll保存在当前解决方案目录的Lib子目录下,该程序集的路径就可以表示成:$(SolutionDir)\Lib\Artech.T4AssemblyRefResovle.Foo.dll。

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="$(SolutionDir)\Lib\Artech.T4AssemblyRefResovle.Foo.dll" #>
<#@ output extension=".cs" #>
public class HelloWorld
{}

注:上面提到的程序集引用解决方案来源于《T4 Template error - Assembly Directive cannot locate referenced assembly in Visual Studio 2010 project.》

程序员的基础教程:菜鸟程序员

解决T4模板的程序集引用的五种方案的更多相关文章

  1. Linux也有后悔药,五种方案快速恢复你的系统

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由信姜缘 发表于云+社区专栏 新手在学习Linux系统的时候,难免会遇到命令输错,或系统出错的难题.那么如何快速解决呢?本文就先给你一个 ...

  2. Redis集群方案怎么做?大牛给你介绍五种方案!

    Redis集群方案 Redis数据量日益增大,而且使用的公司越来越多,不仅用于做缓存,同时趋向于存储这块,这样必促使集群的发展,各个公司也在收集适合自己的集群方案,目前行业用的比较多的是下面几种集群架 ...

  3. Swift 学习笔记 (解决Swift闭包中循环引用的三种方法)

    话不多说 直接上代码 class SmartAirConditioner { var temperature:Int = //类引用了函数 var temperatureChange:((Int)-& ...

  4. 【转载】解决繁体、日文游戏乱码的五种方法 转载自:http://tieba.baidu.com/p/488627981

    方法1:转换区域 开始——设置——控制面板——区域和语言选项——分别选择“高级”和“区域选项”标签——在其下拉框中都选择“日语”(或“日本”)(选项有点多,慢慢找)——重启后即可生效. *某影注:日语 ...

  5. Netty解决粘包和拆包问题的四种方案

    在RPC框架中,粘包和拆包问题是必须解决一个问题,因为RPC框架中,各个微服务相互之间都是维系了一个TCP长连接,比如dubbo就是一个全双工的长连接.由于微服务往对方发送信息的时候,所有的请求都是使 ...

  6. 【转】HTML5 本地存储五种方案

    1.LocalStorage LocalStorage就是Key-Value的简单键值对存储结构,Web Storage除了localStorage的持久性存储外,还 有针对本次回话的sessionS ...

  7. 使用T4模板生成代码的学习

    之前做项目使用的都是Db First,直接在项目中添加Entity Framework,使用T4模板(T4模板引擎之基础入门)生成DAL BLL层等(T4模板是一个同事给的,也没有仔细研究,代码如下: ...

  8. T4模板使用记录,生成Model、Service、Repository

    自己目前在搭建一个.NET Core的框架,本来是打算使用前端做代码生成器直接生成到文件的,快做好了.感觉好像使用T4更方便一些,所以也就有了这篇文章~  我还是有个问题没解决,就是我想生成每个类(接 ...

  9. Asp.net MVC企业级开发(09)---T4模板

    T4即为Text Template Transformation Toolkit,一种可以由自己去自定义规则的代码生成器.根据业务模型可生成任何形式的文本文件或供程序调用的字符串 在VS中T4模板是没 ...

随机推荐

  1. MySQL主从报错解决:Failed to initialize the master info structure

    大清早收到一个MySQL的自定义语言告警 :replication interrupt,看来是主从同步报错了. 登陆MySQL,执行 show slave status \G 发现salve已经停止了 ...

  2. 3.JMeter添加集合点

    1.JMeter的集合点是通过添加定时器来完成的,在做性能测试时,真正的并发是不可能的,为了更真实的模拟并发场景,因此在需要压测的地方设置集合点,即可一起操作发送请求. 2.JMeter添加定时器,右 ...

  3. Android 从上层到底层-----kernel层

    CPU:RK3288 系统:Android 5.1 功能:上层 app 控制 led 亮灭 开发板:Firefly RK3288 1.在dts文件中增加 led 设备 path:kernel/arch ...

  4. C# 7.0 新特性收集

    1.out-variables(Out变量) 2.Tuples(元组) 3.Pattern Matching(匹配模式) 4.ref locals and returns (局部变量和引用返回) 5. ...

  5. Linux c- libevent

    libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名分布式缓存软件memcached也 ...

  6. Android 语音处理

    开源的sip android 项目 https://code.google.com/p/csipsimple/

  7. Linux 发展史

    操作系统 英文名称为operating system,简称os,是应用程序运行及用户操作必备的基础环境支撑,计算机系统的核心,作用是管理和控制计算机系统中的硬件和软件资源 操作系统就是处于用户与计算机 ...

  8. Repeater,ItemDataBound事件,获取绑定列的值,给指定列添加js方法

    protected void rp_bf_ItemDataBound(object sender, RepeaterItemEventArgs e) { if (e.Item.ItemType == ...

  9. 在SpringMVC中使用@RequestBody和@ResponseBody注解处理json时,报出HTTP Status 415的解决方案

    我在使用SpringMVC的@RequestBody和@ResponseBody注解处理JSON数据的时候,总是出现415的错误,说是不支持所提交数据格式,我在页面中使用了JQuery的AJAX来发出 ...

  10. 浅谈PHP面向对象编程(七、抽象类与接口)

    7.0 抽象类与接口 当定义一个类时,常常需要定义一些方法来描述该类的行为特征.但有时这些方法的实现方式是无法确定的,此时就可以使用抽象类和接口. 抽象类和接口用于提高程序的灵活性.抽象类是一种特殊的 ...