【问题标题】:cast problem from class to interface将问题从类转换为接口
【发布时间】:2011-01-18 22:00:15
【问题描述】:
Assembly assembly = Assembly.LoadFrom("Logic\\bin\\Debug\\Logic.dll");
            Type queryManagerType = assembly.GetType("Logic." + HttpContext.Current.Session["lang_name"] + "SearchQueryManager");
            var queryManager = (ISearchQueryManager)Activator.CreateInstance(queryManagerType);


public interface ISearchQueryManager
    {
        IList<Advertisements> ApplyQueries(string searchQuery, int page, int pageSize, string orderBy, out int count);
    }

public class SlovenianSearchQueryManager : ISearchQueryManager
    {
...
}

但我明白了

无法将“Logic.SlovenianSearchQueryManager”类型的对象转换为“Logic.ISearchQueryManager”类型。

编辑:整个堆栈跟踪

System.InvalidCastException 是 用户代码未处理
Message="无法转换类型的对象 'Logic.SlovenianSearchQueryManager' 到 输入“Logic.ISearchQueryManager”。”
Source="ViaMura.Web.Module"
堆栈跟踪: 在 ViaMura.Web.Module.WebController.GetAdvertismentsByRawQuery(字符串 rawQuery, Int32 page, Int32 pageSize, 字符串 orderBy, Int32& count) in D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web.Module\WebController.cs:line 32 在 ViaMura.Web.Module.Views.SearchResultsPresenter.OnResultsLoad(Int32 page, Int32 pageSize, String orderBy) 在 D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web.Module\Views\SearchResultsPresenter.cs:line 43 在 ViaMura.Web.SearchResults.SearchAdvertisments() 在 D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web\SearchResults.aspx.cs:line 155 在 ViaMura.Web.SearchResults.Page_Load(对象 发件人,EventArgs e) 在 D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web\SearchResults.aspx.cs:line 149 在 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, 对象 o, 对象 t, EventArgs e) 在 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(对象 发件人,EventArgs e) 在 System.Web.UI.Control.OnLoad(EventArgs e) 在 ViaMura.Web.App_Code.PageControllers.BasePage.OnLoad(EventArgs e) 在 D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web\App_Code\PageControllers\BasePage.cs:89 行 在 System.Web.UI.Control.LoadRecursive() 在 System.Web.UI.Page.ProcessRequestMain(布尔 includeStagesBeforeAsyncPoint,布尔值 includeStagesAfterAsyncPoint)
内部异常:

编辑2:

string a1 = typeof (ISearchQueryManager).Assembly.Location;
string a2 = typeof(SlovenianSearchQueryManager).Assembly.Location

给我同样的结果:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET 文件\root\5438a399\53975f83\assembly\dl3\0f9540b5\15407fe2_5db7cb01\Logic.DLL

但是

string a3 = queryManagerType.Assembly.Location;

给了我不同的路径:

D:\PROJEKTI\crawler\WebCrawlerSuite\WebCrawler.Logic\bin\Debug\WebCrawler.Logic.dll

【问题讨论】:

  • 请发布完整的异常堆栈跟踪。我怀疑你在两个不同的程序集中定义了这个ISearchQueryManager 接口。
  • @Darin 或两个命名空间

标签: c#


【解决方案1】:

根据我的经验,像这样的类型不匹配问题总是由从两个不同位置加载类型引起的,即使您认为它们应该从同一个位置加载。

比较:Two Types not equal that should be

尝试在调试器中查看每种类型的 Assembly.Location 属性:

typeof(ISearchQueryManager).Assembly.Location
typeof(SlovenianSearchQueryManager).Assembly.Location

【讨论】:

  • 谢谢我使用了错误的程序集。不,我使用 Assembly.Load from 而不是 Assembly.LoadFrom
【解决方案2】:

发生这种情况的一个可能原因是您在两个不同的程序集中定义了这个ISearchQueryManager 接口,实际上它们并不代表相同的类型。我看到您正在玩动态程序集加载。因此,您静态转换为的接口不是SlovenianSearchQueryManager 类实现的接口,即使它具有相同的名称。

【讨论】:

  • 嗨,没有 ISearchQueryManager 接口只在一个程序集中。
  • 这是一个 ASP.NET 网站还是 ASP.NET 应用程序? App_Code 文件夹中有一些代码吗?检查您的 bin 文件夹中是否存在您可能已重命名并忘记但仍包含旧界面的恶意程序集。
  • 我清理项目并重建它。这是aspx 网站。我有 app_code 但那里没有接口。
  • 那么接口在哪里呢?它是否在您动态加载的程序集中定义?你是否也静态引用了这个程序集(我猜你这样做是因为你正在转换到这个接口,所以它在编译时就知道了)?
  • 接口在另一个程序集中,是的,但我也通过代码和引用调用此程序集。你说得对,我两次调用程序集。
【解决方案3】:

您可以尝试在转换之前从创建的对象中打印出接口吗(Type.GetInterfaces())。?这可能会让您了解暴露了哪些接口,并且您正在得到您认为正在得到的东西。 或使用 Activator.CreateInstance(String, String) 变体并传递程序集名称。

【讨论】:

  • 是的,我通过项目引用而不是程序集调用接口。我也可以从程序集中调用它吗?
【解决方案4】:

您可能需要这样做:

在您的应用程序启动代码中的某处注册此事件(Program.cs 是一个好地方):

    //Since we'll be dynamically loading assemblies at runtime, we need to add an appropriate resolution path
    //Otherwise weird things like failing to instantiate TypeConverters will happen
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

然后这样处理:

    private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var domain = (AppDomain) sender;

        foreach (var assembly in domain.GetAssemblies())
        {
            if (assembly.FullName == args.Name)
                return assembly;
        }

        return null;
    }

我的理解是,这将确保动态加载的程序集将使用已加载的程序集解决其依赖关系,而不是加载已加载程序集的新副本。这可以防止您观察到相同类型无效的问题类型,因为它是在程序集的不同副本的上下文中加载的。

【讨论】:

    【解决方案5】:

    接口是否在两个程序集中定义了两次?当我在认为 VS 会移动它的项目之间拖放一个界面时,这发生在我身上,但实际上该界面被复制了。

    我通过查看每种类型的 Assembly.Location 属性发现了这一点(感谢 Jorgen!)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-31
      相关资源
      最近更新 更多