简体   繁体   中英

How can I create a new instance of a class at run time using c#?

I have the following class which I pass Entity Framework Model when making an instance of it.

public class TableMapper<TSource>
{
    protected IQueryExtractor QueryExtractor { get; set; }
    protected string TableAliasPrefix { get; private set; } 

    public TableMapper(IQueryExtractor queryExtractor, string tableAliasPrefix = null)
    {
        QueryExtractor = queryExtractor;
        TableAliasPrefix = tableAliasPrefix;
    }

    public IReportRelation GetForeignRelation<TProperty>(Expression<Func<TSource, TProperty>> property)
    {
        return new ReportRelation
        {
            Column = GetReportColumn(null, Self, property),
            TableName = this.Table(),
            TableAlias = this.GetSqlAlias(),
            ModelType = typeof(TSource),
            QueryExtractor = this.QueryExtractor
        };
    }

    ...
    ...
    ...
}

I call this above class yet from another class like so

var clientMapper = new TableMapper<Client>(QueryExtractor, "Client");
var = clientMapper.GetForeignRelation(x => x.Id);

Please note that Client is an Entity Framework 6 model.

From within my GetForeignRelation method, I set the type of Client or <TSource> so I can create a new instance of the TableMapper class at run time.

Here is what I tried to do in an attempt to create a new instance of it at run time.

var RunTimeModel = Activator.CreateInstance(relationsMapping.ModelType);
var RunTimeMapper = new TableMapper<RunTimeModel>(relationsMapping.QueryExtractor, relationsMapping.TableAlias);

But that is giving me an error.

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

How can I correctly create a new instance of the same class at run time?

You will get the class name of TSource with

typeof(TSource).Name

You should be able to create an instance with:

var instance = Activator.CreateInstance(typeof(TSource));

as long as the type is in the same assembly Other properties can be use to obtain the full namespace

EDIT:

Do this example apply to your scanario? Had to strip down your provided code as I don't know what's behind it all :)

class Program
{
    static void Main(string[] args)
    {
        var test = new TableMapper<A>();
        var fr = test.GetForeignRelation();
        var type = fr.ModelType;
        var newInstance = Activator.CreateInstance(type);
    }
}

public class TableMapper<TSource>
{

    public TableMapper()
    {
    }

    public ReportRelation GetForeignRelation()
    {
        return new ReportRelation
        {
            ModelType = typeof(TSource)
        };
    }
}

public class ReportRelation
{
    public Type ModelType { get; set; }
}

public class A
{
    public string Test { get; set; }
    public A()
    {
        Test = "Some string";
    }
}

You cannot pass variable to a type parameter

var RunTimeModel = Activator.CreateInstance(relationsMapping.ModelType);
var RunTimeMapper = new TableMapper<RunTimeModel>(relationsMapping.QueryExtractor, relationsMapping.TableAlias)

Because RunTimeModel is not a type but a variable. I think you are missing purpose of method which you are using.

You can use the following code to instantiate your generic type :

var RunTimeMapper = Activator.CreateInstance(typeof(TableMapper<>).MakeGenericType(new[] { relationsMapping.ModelType }), new[] { relationsMapping.QueryExtractor, relationsMapping.TableAlias });

However,the return value type for RunTimeMapper is object.I cann't figure out how to cast RunTimeMapper to its actual type.So,it's a little inconvenient to use.

Referer: How to: Examine and Instantiate Generic Types with Reflection

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM