Reputation: 20916
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
{
...
}
but i get
Unable to cast object of type 'Logic.SlovenianSearchQueryManager' to type 'Logic.ISearchQueryManager'.
EDIT: whole stacktrace
System.InvalidCastException was unhandled by user code
Message="Unable to cast object of type 'Logic.SlovenianSearchQueryManager' to type 'Logic.ISearchQueryManager'."
Source="ViaMura.Web.Module"
StackTrace: at ViaMura.Web.Module.WebController.GetAdvertismentsByRawQuery(String rawQuery, Int32 page, Int32 pageSize, String orderBy, Int32& count) in D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web.Module\WebController.cs:line 32 at ViaMura.Web.Module.Views.SearchResultsPresenter.OnResultsLoad(Int32 page, Int32 pageSize, String orderBy) in D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web.Module\Views\SearchResultsPresenter.cs:line 43 at ViaMura.Web.SearchResults.SearchAdvertisments() in D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web\SearchResults.aspx.cs:line 155 at ViaMura.Web.SearchResults.Page_Load(Object sender, EventArgs e) in D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web\SearchResults.aspx.cs:line 149 at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) at System.Web.UI.Control.OnLoad(EventArgs e) at ViaMura.Web.App_Code.PageControllers.BasePage.OnLoad(EventArgs e) in D:\PROJEKTI\crawler\WebCrawlerSuite\ViaMura.Web\App_Code\PageControllers\BasePage.cs:line 89 at System.Web.UI.Control.LoadRecursive() at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
InnerException:
EDIT2:
string a1 = typeof (ISearchQueryManager).Assembly.Location;
string a2 = typeof(SlovenianSearchQueryManager).Assembly.Location
give me the same result:
C:\Windows\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\5438a399\53975f83\assembly\dl3\0f9540b5\15407fe2_5db7cb01\Logic.DLL
but
string a3 = queryManagerType.Assembly.Location;
gives me different path:
D:\PROJEKTI\crawler\WebCrawlerSuite\WebCrawler.Logic\bin\Debug\WebCrawler.Logic.dll
Upvotes: 6
Views: 3764
Reputation: 424
Is the interface defined twice, in two assemblies? This happened to me when I dragged-and-dropped an interface between projects thinking VS would move it, but the interface was actually copied.
I discovered this by looking at the Assembly.Location property of each type (thanks Jorgen!)
Upvotes: 0
Reputation: 1076
In my experience, type mismatch problems like this are always caused by loading types from two different locations, even if you think they should be getting loaded from the same place.
Compare: Two Types not equal that should be
Try looking at the Assembly.Location property of each type in the debugger:
typeof(ISearchQueryManager).Assembly.Location
typeof(SlovenianSearchQueryManager).Assembly.Location
Upvotes: 10
Reputation: 27495
You may need to do this:
Register for this event somewhere in your application startup code (Program.cs is a good place):
//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;
And then handle it like this:
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;
}
My understanding is that this will make sure that a dynamically loaded assembly will resolve its dependencies using already loaded assemblies rather than loading a new copy of an already loaded assembly. This prevents the type of issues you've observed where the same Type is not valid because it's been loaded in the context of a different copy of the assembly.
Upvotes: 0
Reputation: 886
Can you try printing out the interfaces from the object created before casting it(Type.GetInterfaces() ).? that might give you an idea of what interfaces are exposed and you are getting what you think you are getting.. or using Activator.CreateInstance(String, String) variation and pass the Assembly name as well.
Upvotes: 0
Reputation: 1038830
One possible reason for this happening is that you have this ISearchQueryManager
interface defined in two different assemblies which in fact doesn't represent the same type. I see that you are playing with dynamic assembly loading. So the interface you are statically casting to is not the interface implemented by the SlovenianSearchQueryManager
class even if it has the same name.
Upvotes: 2