Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 反射:如何从使用反射调用的方法中获得结果(并对其执行foreach)?_C#_Reflection_Casting_Generic List - Fatal编程技术网

C# 反射:如何从使用反射调用的方法中获得结果(并对其执行foreach)?

C# 反射:如何从使用反射调用的方法中获得结果(并对其执行foreach)?,c#,reflection,casting,generic-list,C#,Reflection,Casting,Generic List,我想从不同的存储库调用一些方法,并将相同类型的List作为结果,但我不知道如何在没有硬代码的情况下转换结果,也不知道如何在此结果上使用foreach,下面是一个示例: class Person { public string Name { get; set; } } class Animal { public string Name { get; set; } } class PersonRepository { public List<Person> G

我想从不同的存储库调用一些方法,并将相同类型的
List
作为结果,但我不知道如何在没有硬代码的情况下转换结果,也不知道如何在此结果上使用
foreach
,下面是一个示例:

class Person
{
    public string Name { get; set; }
}

class Animal
{
    public string Name { get; set; }
}

class PersonRepository
{
    public List<Person> GetPersons()
    {
          List<Person> list = new List<Person>();

          //Some processing...

          return list;
    }
}

class AnimalRepository
{
    public List<Animal> GetAnimals()
    {
        List<Animal> list = new List<Animal>();

        //Some processing...

         return list;
    }
}

public class ReflectionClass
{
    public List<T> GetResultFromMethodInvoked<T>(string entityName, string repositoryName, string methodName)
    {
        List<T> lists = new List<T>();
        Type entity_type = Type.GetType("Entities." + entityName + " ,Entities");
        Type repository = Type.GetType("Crud." + repositoryName + ", Crud");
        MethodInfo method = repository.GetType().GetMethod(methodName);


        var r= method.Invoke(repository, parameters);


        Convert.ChangeType(r, typeof(List<>).MakeGenericType(new Type[] { entity_type }));

        lists = (List<T>)r;

        return lists;
    }
}

class Program
{
    static void Main(string[] args)
    {
        ReflectionClass reflection = new ReflectionClass();
        /* Should have List<Person> as RESULT */
        reflection.GetResultFromMethodInvoked("Person", "PersonRepository", "GetPersons");

        /* Should have List<Animal> as RESULT */
        reflection.GetResultFromMethodInvoked("Animal", "AnimalRepository", "GetAnimals");
    }
}
班级人员
{
公共字符串名称{get;set;}
}
类动物
{
公共字符串名称{get;set;}
}
类PersonRepository
{
公众人士名单
{
列表=新列表();
//一些处理。。。
退货清单;
}
}
类动物库
{
公共列表获取动物()
{
列表=新列表();
//一些处理。。。
退货清单;
}
}
公共类ReflectionClass
{
公共列表GetResultFromMethodInvoked(string entityName、string repositoryName、string methodName)
{
列表=新列表();
Type entity_Type=Type.GetType(“Entities.+entityName+”,Entities”);
类型repository=Type.GetType(“Crud.”+repositoryName+”,Crud”);
MethodInfo method=repository.GetType().GetMethod(methodName);
var r=method.Invoke(存储库,参数);
Convert.ChangeType(r,typeof(List).MakeGenericType(新类型[]{entity_Type}));
列表=(列表)r;
退货清单;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
ReflectionClass reflection=新的ReflectionClass();
/*因此应该有一份清单*/
GetResultFromMethodInvoked(“Person”、“PersonRepository”、“GetPersons”);
/*因此应该有一份清单*/
reflection.GetResultFromMethodInvoked(“动物”、“动物存储库”、“GetAnimals”);
}
}

在代码中使用泛型
公共列表GetResultFromMethodInvoked(string entityName、string repositoryName、string methodName)

ReflectionClass reflection = new ReflectionClass();
/* Should have List<Person> as RESULT */
List<Person> result = reflection.GetResultFromMethodInvoked<Person>("Person", "PersonRepository", "GetPersons");
ReflectionClass reflection=新的ReflectionClass();
/*因此应该有一份清单*/
List result=reflection.GetResultFromMethodInvoked(“Person”、“PersonRepository”、“GetPersons”);

作为编译器,您不能这样做,因为您不知道运行时的字符串
“Person”
表示
Person
-类型。您不能期望编译器推断运行时提供的类型(例如,通过其名称)

所以你有三个选择

  • 您已经提到了这一点,转换为实际的列表类型,例如
    list
  • 或者,让列表中可能包含的所有类型从公共接口继承并强制转换为接口类型列表

    interface MyInterface
    {
        public string Name { get; set; }
    }
    class Person : MyInterface
    {
        public string Name { get; set; }
    }
    class Animal : MyInterface
    {
        public string Name { get; set; }
    }
    
    现在使用列表的界面:

    var result = reflection.GetResultFromMethodInvoked<MyInterface>("Person", "PersonRepository", "GetPersons");
    foreach(var o in result) 
        Console.WriteLine(o.Name);
    
    为了实现这一点,您的方法当然也应该是非泛型的,因为您不能在该方法之外真正使用泛型类型


  • 这是不可能的,您不能让编译器推断您在运行时提供的类型。您必须在编译时提供泛型类型参数才能使用强类型。不过,您当然可以将结果强制转换到非泛型
    IEnumerable
    -接口并进行迭代。或者创建一个接口,让列表中所有可能的类型实现并转换为
    列表
    。Hi@HimBromBeere,我不确定是否理解good,我是C#新手,你能给我一个你提到的例子吗?多谢各位much@AbdelatifLatrach正如我allready所说的,geeric类型的参数(在括号内,要么是
    (MyType)result
    ,要么是DoSomething()`是编译时信息。但是,以字符串形式提供typename是一种运行时信息,这意味着在实际执行程序时对其进行计算。因此,简短的ANWR是:不,这是不可能的。
    var result = (Enumerable) reflection.GetResultFromMethodInvoked("Person", "PersonRepository", "GetPersons");
    foreach(var o in result) ...