【问题标题】:Casting an object I receive through reflection投射我通过反射收到的对象
【发布时间】:2009-10-27 09:05:33
【问题描述】:

我有这个功能:

程序 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);
}

我正在投射到列表,因为我在 Program B 没有ReportLocationInfo,而且我手头有自己的翻译功能。这当然行不通。

有什么建议吗?

【问题讨论】:

  • 如果您无法访问程序 B 中的 ReportLocationInfo 类,您将如何访问这些数据?
  • Info.GetType().GetProperty("propertyName") 但我还有一个问题,如何访问列表中的每个 ReportInfo?

标签: c# generics reflection casting


【解决方案1】:

ICollection&lt;T&gt; 实现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>
}

【讨论】:

    【解决方案2】:

    您将无法转换为尚未在当前程序集中定义的类或当前程序集引用的程序集。没有办法解决它。出于这个原因,存在静态类型。

    您说您希望它动态翻译,由此我假设您希望它能够获取 Intellisense,即使尚未定义该类,嗯,这是不可能的。

    【讨论】:

    • 我知道,这就是为什么我想在我这边动态翻译它。那可能吗?怎么样?
    【解决方案3】:
    Activator.CreateInstance(typeof(List<>).MakeGenericType(yourtype)) as IList
    

    我不确定您的尝试是否正确。 ReportInfo怎么会突然变成ReporttLocationInfo

    【讨论】:

    • 你是对的,我的错。我把它编辑了。我想将 ReportLocationInfo 放入 Object,因为 ProgramB 中不存在 ReportLocationInfo。能做到吗?
    【解决方案4】:

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

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

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

    从那里开始工作,知道报告实际上是ICollection&lt;ReportLocationInfo&gt; 类型

    【讨论】:

      【解决方案5】:

      一个简单的方法是:

      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 实例上使用反射调用方法几乎就像在做普通的 C。你没有类型安全。

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

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

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

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

      然后在程序B中加载后将每个插件转换为IReportFactory

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-18
        • 2014-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多