简体   繁体   English

如何使用 c# 在运行时创建类的新实例?

[英]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.请注意, Client是实体框架 6 模型。

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.在我的GetForeignRelation方法中,我设置了Client<TSource>的类型,以便我可以在运行时创建TableMapper类的新实例。

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?) RunTimeModel类型或命名空间名称RunTimeModel (您是否缺少 using 指令或程序集引用?)

How can I correctly create a new instance of the same class at run time?如何在运行时正确创建同一类的新实例?

You will get the class name of TSource with您将获得 TSource 的类名

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?此示例适用于您的 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.因为 RunTimeModel 不是类型而是变量。 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.但是RunTimeMapper的返回值类型是object。我不知道如何将RunTimeMapper转换为它的实际类型。所以,使用起来有点不方便。

Referer: How to: Examine and Instantiate Generic Types with Reflection Referer: 如何:使用反射检查和实例化泛型类型

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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