投射我通过反射收到的物体

时间:2009-10-27 09:05:33

标签: c# generics reflection casting

我有这个功能:

计划A

public ICollection<ReportLocationInfo> GetAllReportsInstalled() 
{
    return _Reports;
}

我通过动态反射调用它:

计划B

internal ICollection<Object> Scan(string path)
{
     MethodInfo GetReports =
          _reportFactoryType.GetMethod("GetAllReportsInstalled");

     return (List<Object>)GetReports.Invoke(_reportFactory, null);
}

我正在转向List,因为我在程序B 没有ReportLocationInfo,而且我手头有自己的翻译功能。这当然不起作用。

有什么建议吗?

5 个答案:

答案 0 :(得分:3)

ICollection<T>实施System.Collections.IEnumerable。您可以转换为此接口,然后使用foreach遍历对象。

MethodInfo GetReports = _reportFactoryType.GetMethod("GetAllReportsInstalled");
IEnumerable reports = (IEnumerable)GetReports.Invoke(_reportFactory, null);

foreach (object report in reports)
{
    // Use reflection to read properties or add to a new List<object> if you
    // need an ICollection<object>
}

答案 1 :(得分:0)

您将无法转换为尚未在当前程序集中定义的类或当前程序集引用的程序集。没有办法解决它;因此,静态输入是有的。

你说你想要它动态翻译,我假设你希望它能够获得智能感知,即使该类尚未定义,嗯,这是不可能的。

答案 2 :(得分:0)

Activator.CreateInstance(typeof(List<>).MakeGenericType(yourtype)) as IList

我不确定你的尝试是否正确。 ReportInfo如何突然变为ReporttLocationInfo

答案 3 :(得分:0)

首先,你真的不想这样做。

如果你坚持,你还必须通过反射检查你的GetReports.Invoke调用的返回值。从:

开始
Object reports = GetReports.Invoke(_reportFactory, null);

从那里开始工作,知道报告实际上是ICollection<ReportLocationInfo>

类型

答案 4 :(得分:0)

一种简单的方法是:

private ICollection<object> ScanInternal(string path)
{
     List<object> result = new List<object>();

     MethodInfo GetReports = 
           _reportFactoryType.GetMethod("GetAllReportsInstalled");

     IEnumerable reports = GetReports.Invoke(_reportFactory, null)
           as IEnumerable;

     if (reports != null)  // or exception if null ?
     {
         foreach (object report in reports)
             result.Add(report);
     }

     return result;
}

但更合适的方法是在单独的共享程序集中创建一个界面(例如IReportLocationInfo),然后在两个程序集中使用此界面

考虑重构一下你的代码来实现这一点,因为在object实例上使用Reflection调用方法几乎就像做了简单的C. 你没有类型安全。

因此,OOP的方法是将所有接口放在一个单独的程序集中(由引用程序A和程序B):

public interface IReportFactory
{
     IEnumerable<IReportLocationInfo> GetAllReportsInstalled();
}

public interface IReportLocationInfo
{
     void SomeMethod();
} 

然后在“插件”程序集中实现您的具体工厂(程序A ):

public class MyReportFactory : IReportFactory
{
    // ...
}

然后在程序B 内加载后将每个插件投放到IReportFactory