URL: https://www.overclockers.at/coding-stuff/casting_probleme_in_c_89748/page_1 - zur Vollversion wechseln!
bin gspannt, obma wer helfen kann
also:
ich hab a klasse "BasicModule", die von Windows.Forms.Control abgeleitet ist und das Interface "IModule" implementiert
wenn ich jetzt zur laufzeit dynamisch aus der dll (assembly) ein objekt dieser klasse instanzieren will, kann ichs zwar auf Control, aber net auf IModule casten
damits euch was vorstellen könnts:
Code:public class BasicModule : Control, IModule { ... } public interface IModule { ... } ... ModuleEntity selected = (ModuleEntity)trvQueries.SelectedNode.Tag; object instance = selected.Library.CreateInstance("DAP." + selected.Description.Class,true); pnlModule.Controls.Add((Control)instance); ((IModule)instance).DBConnection = dbConnection; ...
ich habe ein kleines testprogramm gecoded, um das problem zu veranschaulichen:
Code:[b]CastTest.cs[/b] namespace CastTest { public class BaseClass { private int x; public BaseClass() { x = 0; } public int X { set { x = value; } get { return x; } } } public interface ITest { int Square(); } public class TestClass : BaseClass, ITest { public TestClass() { X = 5; } public int Square() { return X*X; } } }
Code:[b]Test.cs[/b] namespace CastTest { public class MainClass { public static void Main(string[] args) { try { object instance = new CastTest.TestClass(); int x = ((CastTest.TestClass)instance).Square(); int y = ((CastTest.ITest)instance).Square(); System.Console.Write("x ok: " + x); System.Console.Write("\ny ok: " + y); } catch (System.Exception e) { System.Console.Write(e.Message); } } } }
Code:[b]Test2.cs[/b] namespace CastTest { public class MainClass { public static void Main(string[] args) { try { System.Reflection.Assembly as = System.Reflection.Assembly.LoadFrom("CastTest.dll"); System.Console.Write("Assembly loaded: " + as.ToString()); object instance = as.CreateInstance("CastTest.TestClass"); System.Console.Write("Instance created: " + instance.ToString()); int x = ((CastTest.ITest)instance).Square(); int y = ((CastTest.TestClass)instance).Square(); System.Console.Write(x); } catch (System.Exception e) { System.Console.Write("\n" + e.Message); } } } }
Jetzt wollt ich mich schon beschweren, dass das so ein unübersichtlicher Post ist, dass ihn eh keiner lesen wird, aber das ist gar nicht der Fall.
Das ist jedenfalls ein interessantes Problem, das du hier hast. Würd mich interessieren, woher das kommt. Leider bin ich mit .NET nicht sehr bewandert, hab nur ein paarmal reingeschnuppert.
Ich hätt mir gedacht, dass er vielleicht das Interface zur Laufzeit gar nicht kennt, aber durch die Reference sollte er das doch wohl.
nagut, ich hab das problem jetzt umgangen, indem ich auf die Reflection-methoden umgesattelt hab
ist zwar net wirklich schön, aber es funktioniert wenigstens
FYI: über die Reflection klassen kann man sich zur laufzeit jegliche informationen über ein objekt, klasse, assembly etc holen
sowohl name, methoden, interfaces, berechtigungen und und und
und diese natürlich dann manipulieren
Code:namespace CastTest { public class MainClass { public static void Main(string[] args) { try { System.Reflection.Assembly ass = System.Reflection.Assembly.LoadFrom("CastTest.dll"); System.Console.Write("Assembly loaded: " + ass.ToString()); object instance = ass.CreateInstance("CastTest.TestClass"); System.Console.Write("Instance created: " + instance.ToString()); int v = 100; instance.GetType().GetProperty("X").SetValue(instance,(object)v,null); int x = (int)instance.GetType().GetMethod("Square").Invoke(instance,null); //int x = ((CastTest.ITest)instance).Square(); System.Console.Write(x); } catch (System.Exception e) { System.Console.Write("\n" + e.Message); } } } }
nach einigem herumforschen in newsgroups hab ich jetzt die lösung gefunden bzw die ursache für das problem
und zwar:
der cast ist deswegen ungültig, weil die definition für das interface sowohl in der assembly, als auch in laufenden programm reincompiliert ist, d.h. man hat zur laufzeit zwei idente definitionen -> runtime kann sich nicht entscheiden und wirft exception
umgehen kann man also nun das ganze, in dem man das interface in eine eigene assembly kompiliert und alle anderen assemblies/executables dann mit verweis auf diese assembly compiliert
code mit den casts drinnen so verändern, dass jede klasse und das interface jeweils in einer eigenen datei ist, und dann neu compilieren:
csc /target:library /out:ITest.dll ITest.cs
csc /target:library /out:BaseClass.dll BaseClass.cs
csc /target:library /out:TestClass.dll TestClass.cs /reference:ITest.dll /reference:BaseClass.dll
csc Test.cs /reference: TestClass.dll
und siehe da, es funzt !
Thanks for the info. Jetzt noch den Thread auf SOLVED stellen, und es ist perfekt
bittesehr
btw: soll deine sig "no space left on this device" heissen?
babelfish ownage
But of course
overclockers.at v4.thecommunity
© all rights reserved by overclockers.at 2000-2025