以编程方式获取类型并将其用作类型参数

时间:2015-06-10 13:56:50

标签: c# windows-phone-8.1 win-universal-app type-parameter

我想要做的是阅读我的lex.db数据库中的所有内容。优选地,通过寻呼具有预定义大小的页面。我做了以下事情:

DbInstance database = GetDatabase();
var tables = database.AllTables();
foreach (var table in tables)
{
    string str = table.ToString();
    str = str.Replace("Lex.Db.DbTable`1[", string.Empty);
    str = str.Replace("]", string.Empty);
    Type t = Type.GetType(str);

    if (t != null)
    {
    var columns = database.ReadAll<t>();
    //handle all columns
    }
}

问题是函数ReadAll有一个typeparam。我假设我可以使用type作为typeparam,因为它代表了我想要的类。

然而我收到错误:

  

“无法找到类型或命名空间名称't'(你错过了吗?   使用指令或汇编引用?)“。

那么如何才能将实际类型用作typeparam而不是字母't'?

我正在为Windows 8.1和Windows Phone 8.1创建一个Windows通用应用程序

编辑:

根据romkyns和Stefan Steinegger给出的建议,我尝试使用反射。我现在有以下代码:

DbInstance database = DbInstance.GetInstance();

System.Type thisType = database.GetType();
TypeInfo thisTypeInfo = thisType.GetTypeInfo();
MethodInfo method = thisTypeInfo.GetDeclaredMethod("LoadAll");

var tables = database.AllTables();
foreach (var table in tables)
{
    string str = table.ToString();
    str = str.Replace("Lex.Db.DbTable`1[", string.Empty);
    str = str.Replace("]", string.Empty);
    Type t = Type.GetType(str);
    if (t != null)
    {
        MethodInfo generic = method.MakeGenericMethod(t);
        object[] parameters = { this, null };
        var columns = generic.Invoke(database, parameters);

        if (columns != null)
        {
            //handle columns
        }
    }
}

这可以调用invoke方法。此时会发生以下异常:

  

mscorlib.dll中出现“System.Reflection.TargetException”类型的异常,但未在用户代码中处理

     

其他信息:对象与目标类型不匹配。

有关如何解决此问题的任何线索?

编辑II:

必须将调用方法调用为:

var columns = generic.Invoke(database, null);

2 个答案:

答案 0 :(得分:1)

拨打电话的唯一方法是use reflection<T>应该在编译时知道,但在你的情况下它不是,因此你不能这样做。

此类API通常会带有一个直接占用Type的重载。检查你的是否有它。它可能看起来像这样:

database.ReadAll(t);

答案 1 :(得分:1)

你必须使用反射。不可能以另一种方式将运行时类型与编译时类型组合在一起:

(可能是错的,只是内心看起来像这样:)

var dbInstanceType = typeof(DbInstance);
var readAllMethod = dbInstanceType.GetMethod("ReadAll");
var typedReadAllMethod = readAllMethod.BuildGenericMethod(t);
var result = typedReadAllMethod.Invoke(dbInstanceType);

通常你有一个非泛型方法来传递运行时类型,因为在这种情况下泛型没有意义。