문제

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).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top