qex Posted February 2, 2005 Posted February 2, 2005 I am trying to use CreateInstance and I keep getting an <undefined value> returned from CreateInstance. It doesn't through an exception though and I thought if it didn't find the interface that it was supposed to do that. So I guess my question is how do I make sure that I am passing createInstance the correct interface name. public object CreateInstance(string dllname,string strInterface) { Assembly objDLL; object objPlugin; try { //load dll //C:\Projects\PrintRoutineXP\bin\PrintRoutineXP.dll objDLL = Assembly.LoadFrom(dllname); //create and return class instance objPlugin = objDLL.CreateInstance(strInterface); return objPlugin; } catch(Exception e) { myLog.Log(string.Format("Error trying to create Instance of a plugin. Name: {0} Error: {1}",dllname,e.Message)); return null; } } Quote
Administrators PlausiblyDamp Posted February 2, 2005 Administrators Posted February 2, 2005 You cannot create an instance of an interface - only classes; in your case a class that implements the interface would be expected. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
qex Posted February 2, 2005 Author Posted February 2, 2005 You cannot create an instance of an interface - only classes; in your case a class that implements the interface would be expected. So if my code is setup like below would I pass createInstance("testParser.TestParser"); namespace testParser { /// <summary> /// Summary description for Class1. /// </summary> public class TestParser:Interface.IParser { } . . . } Quote
Administrators PlausiblyDamp Posted February 2, 2005 Administrators Posted February 2, 2005 From the look of it that should work. Also if you have a look through the tutor's corner on this forum there is s good example of using interfaces / reflection to create a plugin based application - might be worth a read. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
qex Posted February 8, 2005 Author Posted February 8, 2005 I had the above code working, but it seems that I am doing something wrong and I'm not sure what the best way to debug it is. I'm using Assembly.loadfrom and createInstance and am getting an instance of my test class back in object form which I return to another function where I'm trying to cast it to my Interface name with no luck it returns a undefined value. The dll that is being loaded uses Interface.IParser as one of its base classes, but when I try to make it return as Interface.IParser objPlugin = <undefined value>. If I change objPlugin to an object I get the instance of my testParser class, so its loading the dll it just can't find a way to cast it to Interface.IParser... how can I find out why that is happening Interface.IParser objPlugin; Interface.PluginServices parserService = new Interface.PluginServices(); objPlugin = parsserService.CreateInstance(_parser) as Interface.IParser; return objPlugin.ParserName; Quote
Administrators PlausiblyDamp Posted February 8, 2005 Administrators Posted February 8, 2005 If you step through the code does the CreateInstance method inside the DLL work every step of the way? If not which line within the DLL fails (probably on assembly.CreateInstance). What is the value of _parser when you run the above code? Does it contain the name of a valid class? Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
qex Posted February 8, 2005 Author Posted February 8, 2005 Below is the code for my CreateInstance function so _parse is a struct that contains the full location and name of the dll to load as well as the class name. This code functions correctly objPlugin just before return is = to an instance of the class contained in the dll{testParser.TestParser}. When I try to cast it to Interface.IPlugin in the function that takes the return from below it ends up being undefined public object CreateInstance(AvailablePlugin Plugin) { Assembly objDLL; object objPlugin; try { //load dll objDLL = Assembly.LoadFrom(Plugin.AssemblyPath); //create and return class instance objPlugin = objDLL.CreateInstance(Plugin.ClassName); return objPlugin; } catch(Exception e) { myLog.Log(string.Format("Error trying to create Instance of a plugin. Name: {0} Error: {1}",Plugin.ClassName,e.Message)); return null; } } Quote
Administrators PlausiblyDamp Posted February 8, 2005 Administrators Posted February 8, 2005 Does the class objPlugin is set to implement the IPlugin interface? Also wher eis the IPlugin interface defined (in a shared library etc)? Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
qex Posted February 8, 2005 Author Posted February 8, 2005 Ok this makes no sense to me now. If you look at the code below you see where I was playing around and use myP to create and instance of testParser.dll... which works it returns the instance of the class contained in the dll cast to Interface.IParser. And if you look further down in the code you see the call to parserFuncs.getParserName(parsers)); This calls the code that I have been describing earlier and it works too now, but if I comment out the line: Interface.IParser mytest = myP.CreateInstance(pars) as Interface.IParser; then the second call to CreateInstance that is contained in parserFuncs.getParserName(parsers) fails... this makes no sense. why calling my CreateInstance earlier in the code works and makes the second call work too. They both create instances of the exact same class and call the same method within that class. private void Form1_Load(object sender, System.EventArgs e) { DirectoryInfo myDirInfo = new DirectoryInfo (Application.StartupPath); DirectoryInfo myparentDirInfo = myDirInfo.Parent; parserFuncs = new Parser(); Interface.PluginServices myP = new Interface.PluginServices(); Interface.PluginServices.AvailablePlugin pars = new Interface.PluginServices.AvailablePlugin(); pars.AssemblyPath = "C:\\Projects\\testParser\\bin\\Debug\\testParser.dll"; pars.ClassName = "testParser.TestParser"; Interface.IParser mytest = myP.CreateInstance(pars) as Interface.IParser; . . . if(parserPath.Text != "") { parsers = parserFuncs.getListofParsers(MakeValidPath(parserPath.Text)); if (parsers != null) { for(int i = 0; i< parsers.Length; i++) { parserComboBox.Items.Add(parserFuncs.getParserName(parsers[i])); } } } } getParserName is try { Interface.IParser objPlugin; //object ob; Interface.PluginServices parserService = new Interface.PluginServices(); //ob = parserService.CreateInstance(_parser); objPlugin = parserService.CreateInstance(_parser) as Interface.IParser; //objPlugin = ob as Interface.IParser; //return ob.ToString(); return objPlugin.ParserName; } catch(Exception e) { myLog.Log(string.Format("Error getting parser name: {0}",e.Message)); return ""; } Quote
qex Posted February 8, 2005 Author Posted February 8, 2005 Does the class objPlugin is set to implement the IPlugin interface? Also wher eis the IPlugin interface defined (in a shared library etc)? the Interface is defined in a shared library The class I'm trying to implement is defined below where Interface.IParser is my interface that I have defined. namespace testParser { public TestParser:genParser,Interface.IParser { } } Quote
qex Posted February 8, 2005 Author Posted February 8, 2005 I'm trying to look at what could be different here... the form_load is happening in one project and the getParserName in another(same solution though), but the references to the interface are(should) be the same because the Interface project is in my current solution and I'm referencing the project directly rather than just the created dll Quote
Administrators PlausiblyDamp Posted February 8, 2005 Administrators Posted February 8, 2005 If possible could you attach the source to the projects - it might be easier to see what is going on with more code to look at. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
qex Posted February 9, 2005 Author Posted February 9, 2005 (edited) Here is my code paired down... I hope you can make something out of it. I created a new solution so if you unzip the files to the desktop it should work. If you run as is all it will do is pop up a message box that says TestParser. if you comment out the 9th line in the form load of testpluginform then the whole thing doesn't work... the problem is happening when I try to cast the object being returned to Interface.IParser... Thank you very muchtestparser.zip Edited February 11, 2005 by PlausiblyDamp Quote
qex Posted February 14, 2005 Author Posted February 14, 2005 any luck with this. It still doesn't make any sense. Any help with ideas about how to try to debug it or directions to take would be appreciated. Thanks for your help Quote
Administrators PlausiblyDamp Posted February 14, 2005 Administrators Posted February 14, 2005 Only had time for a quick look - strange how it seems to work one way but not the other... I could only see one declaration for the testParser class - it isn't declared anywhere else is it? Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
qex Posted February 16, 2005 Author Posted February 16, 2005 Only had time for a quick look - strange how it seems to work one way but not the other... I could only see one declaration for the testParser class - it isn't declared anywhere else is it? Nope that is it... just that one place. Quote
qex Posted April 14, 2005 Author Posted April 14, 2005 still having problems with this. It seems the problem is is not that createInstance fails but that I am returning the instance created and it is not able to be cast from testParser.TestParser which implements Interface.IParser to Interface.IParser. objPlugin = parserService.CreateInstance(_parser) as Interface.IParser; like I said abouve parserService.CreateInstance(_parser) returns and instance of testParser.TestParser which I'm then trying to cast to Interface.IParser. it says this cast is invalid, but I don't know why because testParser.TestParser implements Interface.IParser. Any Help will be appreciated. Thanks Quote
qex Posted May 6, 2005 Author Posted May 6, 2005 Well after a long time of looking around and just plain looking confused. This article explains the problem I was having. http://www.gotdotnet.com/team/clr/LoadFromIsolation.aspx Essentially what it was is that I referenced my Interface class at Design time and then I loaded my plugin dll at runtime from a different directory well the CLR differentiates between the two types of references especially since the one at run time was from a different directory then the exe and the statically referenced dll so they were seen as not being the same type even though they were based on the same class... Assembly a = Assembly.LoadFrom(c:\\temp\\Regcode.dll); Object o = a.CreateInstance(Regcode.UtilClass); Regcode.UtilClass x = (Regcode.UtilClass)o; //FAIL! As you can infer from this cast failure, the CLR considers the two instances of Regcode.UtilClass to be completely different types. So to fix this I had to move the plugin to the same folder as the exe so that the CLR will know they are the same base class... So that is all for my poor explanation... The article explains it pretty well. Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.