Matt
Matt

Reputation: 53

C# generic types at runtime

I'm trying to dynamically generate reports and email them to the appropriate users is this possible or can does the compiler need the type before runtime.

static void Main(string[] args) {
    ArrayList ReportsTypes = new ArrayList();
    ReportsTypes.Add(typeof(AgentPPL));
    foreach(Type t in ReportsTypes) {
        InitilizeReports<t>(); // <- Error
    }
}
static void InitilizeReports<T>() where T : new() {
    T r = new T();
    IReportDocument rd = (IReportDocument)r;
    rd.DocumentName = "SomeReport";
    ExportReport(rd);
}

What I'd really like to do is grab a string out of the database and convert the string to a type but I doubt thats possible but what about creating an array of types like in my example what am doing wrong here. Any help is much appreciated I've been spinning my wheels for a while just to get my templates working.

Upvotes: 1

Views: 226

Answers (4)

DmitryG
DmitryG

Reputation: 17848

You can use one of the following approaches:

ReportGenerator generator = new ReportGenerator();
// 1. Invoke method with single parameter
foreach(Type t in ReportsTypes) {
    generator.InitilizeReportsByType(t);
}
// 2. Make and invoke generic method without parameter via reflection
MethodInfo mInfo = typeof(ReportGenerator).GetMethod("InitilizeReportsGeneric");
foreach(Type t in ReportsTypes) {
    MethodInfo genericMethod = mInfo.MakeGenericMethod(new Type[] { t });
    genericMethod.Invoke(generator, new object[] { });
}


public class ReportGenerator {
    public void InitilizeReportsByType(Type type) {
        IReportDocument reportDocument = (IReportDocument)Activator.CreateInstance(type);
        //...
    }
    public void InitilizeReportsGeneric<T>() where T : IReportDocument, new() {
        T reportDocument = new T();
        //...
    }
}

Note, that T reportDocument = new T() are equal to Activator.CreateInstance(type) because it is only compiler syntax sugar.

Upvotes: 1

Wolfgang Ziegler
Wolfgang Ziegler

Reputation: 1685

You could modify the code just a bit and use reflection instead:

static void Main(string[] args)
{
    ArrayList ReportsTypes = new ArrayList();
    ReportsTypes.Add(typeof(AgentPPL));


    foreach (Type t in ReportsTypes)
    {
        InitilizeReports(t);
    }


}

static void InitilizeReports(Type t)
{
    var r = Activator.CreateInstance(t);
    AgentPPL rr = new AgentPPL();
    IReportDocument rd = (IReportDocument)r;
    rd.DocumentName = "SomeReport";
    ExportReport(rd);
}

Upvotes: 0

Patrick McDonald
Patrick McDonald

Reputation: 65441

You can create an instance of a class from a string as follows:

Type reportType = Type.GetType("ClassName.Including.Namespace");
IReportDocument report = (IReportDocument)Activator.CreateInstance(reportType);

Upvotes: 0

naspinski
naspinski

Reputation: 34707

You can convert a string to a Type with Type.GetType(string typeName):

Type intType = Type.GetType("System.Int32");

Upvotes: 0

Related Questions