创建泛型列表< T> T4生成类型 [英] Create generic List<T> of T4 generated type

查看:127
本文介绍了创建泛型列表< T> T4生成类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用T4技术创建了简单的课程。

 <#@ template debug =falsehostspecific =falselanguage =C##> 
<#@ output extension =。cs#>
使用System;

<#var properties = new String [] {P1,P2,P3}; #>
public class MyGeneratedClass {
<#
for(int i = 0; i< 3; i ++)
{
#>
private Int32 _<#= properties [i]#> =<#= i#>;
public Int32<#= properties [i]#>
{
get
{
return _<#= properties [i]#>;
}
}
<#
}
#>
}

然后我创建了一个像这样生成的类型的实例

  static void Main(String [] args)
{
var template = new Template1();
var text = template.TransformText();

CodeDomProvider codeProvider = new CSharpCodeProvider();
ICodeCompiler compiler = codeProvider.CreateCompiler();

//添加编译参数
var compilerParams = new CompilerParameters
{
CompilerOptions =/ target:library / optimize,
GenerateExecutable = false,
GenerateInMemory = true,
IncludeDebugInformation = false
};
compilerParams.ReferencedAssemblies.Add(mscorlib.dll);
compilerParams.ReferencedAssemblies.Add(System.dll);

//编译代码
var compilerResults = compiler.CompileAssemblyFromSource(compilerParams,text);

if(compilerResults.Errors.HasErrors)
throw new Exception();

//Создаемэкземпляркласса
var instance = compilerResults.CompiledAssembly.CreateInstance(MyGeneratedClass);
if(instance == null)
return;

var TYPE = instance.GetType();
var list = new List< TYPE>();


var list = new List< TYPE>(); 生成编译时错误:


类型或名称空间名称'TYPE'找不到(是否缺少使用指令或程序集引用?)





  1. 是否有任何方法来创建类型为 MyGeneratedClass 类的泛型列表(或一些泛型集合)?

  2. 创建 MyGeneratedClass 类的实例的方法


解决方案

 类型genericListType = typeof(List<>); 
类型[] typeArgs = new [] {instance.GetType()};
var generic = genericListType.MakeGenericType(typeArgs);
System.Collections.IList list =(System.Collections.IList)Activator.CreateInstance(generic);

foreach(列表中的动态项目)
{
//任何
}

希望我帮你解决了问题。



编辑一些更实用的东西,

这种方法对于 ArrayList 没有太大的优势,如果您尝试添加与特定运行时类型不同的东西,那么在运行时会出现异常。虽然 ArrayList 不会在添加错误项目的情况下抛出异常,但如果您使用这些项目,将会或不会有例外。我这样做(即使我在编译时不知道类型)尝试使用具体泛型而不是开放的 ArrayList ,因为异常是在正确的代码行(IMHO)引发的。


I created simple class using T4 technology.

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
using System;

<# var properties = new String[]{"P1", "P2", "P3"}; #>
public class MyGeneratedClass {
<#  
    for(int i = 0; i < 3; i++)
    {
    #>
        private Int32 _<#= properties[i] #> = <#= i #>;
        public Int32 <#= properties[i] #> 
        {
            get 
            {
                return _<#= properties[i] #>;
            }
        } 
    <#
    }
    #>
}

then I created an instance of that generated type like this

static void Main(String[] args)
{
    var template = new Template1();
    var text = template.TransformText();

    CodeDomProvider codeProvider = new CSharpCodeProvider();
    ICodeCompiler compiler = codeProvider.CreateCompiler();

    // add compiler parameters
    var compilerParams = new CompilerParameters
    {
        CompilerOptions = "/target:library /optimize",
        GenerateExecutable = false,
        GenerateInMemory = true,
        IncludeDebugInformation = false
    };
    compilerParams.ReferencedAssemblies.Add("mscorlib.dll");
    compilerParams.ReferencedAssemblies.Add("System.dll");

    // compile the code
    var compilerResults = compiler.CompileAssemblyFromSource(compilerParams, text);

    if (compilerResults.Errors.HasErrors)
        throw new Exception();

    // Создаем экземпляр класса
    var instance = compilerResults.CompiledAssembly.CreateInstance("MyGeneratedClass");
    if (instance == null)
        return;

    var TYPE = instance.GetType();
    var list = new List<TYPE>(); 

}

var list = new List<TYPE>(); generate compile time error:

The type or namespace name 'TYPE' could not be found (are you missing a using directive or an assembly reference?)

  1. Is there any way to create generic list (or some generic collection) with the type of MyGeneratedClass class?
  2. And is there simpler way to create instance of MyGeneratedClass class?

解决方案

Type genericListType = typeof(List<>);
Type[] typeArgs = new[] { instance.GetType() };
var generic = genericListType.MakeGenericType(typeArgs);
System.Collections.IList list = (System.Collections.IList)Activator.CreateInstance(generic);

foreach (dynamic item in list)
{
//whatever
}

Hope i got you right..

EDIT something more usable,

This approach has not much advantages to a ArrayList just there are Exceptions at runtime if you try to add something different then the specific runtime type. While ArrayList will not throw an exception in the case the "wrong" item is added instead there will or will not be an exception if you use the items. I do (even if i don't know the Type at compile time) try to use the concrete generic instead of an open ArrayList, because the exception is raised at the right codeline (IMHO).

这篇关于创建泛型列表&lt; T&gt; T4生成类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆