27. oktober 2004 - 20:04
Der er
17 kommentarer og 1 løsning
Bruge class i assembly
Hejsa, er løbet ind i et lille problem med hensyn til at loade assemblies i C# Jeg har en række klasser, der nedarver fra følgende interface: Interface.dll -------------------------------------- namespace DriverInterface { public abstract class StreamInterface : System.IO.Stream { #region constructor public StreamInterface(string connection) { } #endregion } } -------------------------------------- Når jeg vil loade en instans af en dll, der nedarver fra interfacet gør jeg sådan her: Client.exe -------------------------------------- public sealed class Driver { public DriverInterface.StreamInterface RequestStream(string assemblyName, string connection) { System.Reflection.Assembly DataProvider; DataProvider = System.Reflection.Assembly.LoadFrom(assemblyName); DriverInterface.StreamInterface instance = (DriverInterface.StreamInterface) DataProvider.CreateInstance( "DriverInterface.StreamInterface"); return instance; } } -------------------------------------- Er dette den rigtige måde at gøre det på? og hvordan får jeg overført variablen connection til constructoren? På forhånd tak!
Annonceindlæg fra Conscia
27. oktober 2004 - 20:13
#1
Den nemmeste løsning er at lave en constructor uden argumenter og enten en Property eller en Set metode til at sætte connection med.
27. oktober 2004 - 20:16
#2
Ellers tror jeg at du skal igang med GetType() og GetConstructors() og Invoke()
27. oktober 2004 - 20:16
#3
Hvis du vil den sidste vej kan jeg godt forsøge at bixe et eksempel.
27. oktober 2004 - 20:19
#4
Vil super gerne se et eksempel på det sidste.
27. oktober 2004 - 20:23
#5
Jeg går igang
27. oktober 2004 - 20:34
#6
Har fundet ud af at CreateInstance tager "object[] args", men ved ikke rigtigt hvad de andre argumenter betyder... [C#] public object CreateInstance( string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture, object[] activationAttributes );
27. oktober 2004 - 20:38
#7
A.cs ==== using System; public abstract class A { private int v; public A(int v) { this.v = v; } public abstract int GetOffset(); public void Show() { Console.WriteLine(v + GetOffset()); } } C.cs ==== public class C : A { private int offset; public C(int v, int offset) : base(v) { this.offset = offset; } public override int GetOffset() { return offset; } } Test.cs ======= using System; using System.Reflection; class TestClass { public static void Test(string dllname, string classname, int v, int offset) { Assembly asm = Assembly.Load(dllname); Type typ = asm.GetType(classname); Type[] ctordeclargs = { typeof(int), typeof(int) }; ConstructorInfo ctor = typ.GetConstructor(ctordeclargs); object[] ctorcallargs = { v, offset }; A o = (A)ctor.Invoke(ctorcallargs); o.Show(); } public static void Main(string[] args) { Test("C", "C", 1, 2); } } build ===== csc /t:library A.cs csc /r:A.dll /t:library C.cs csc /r:A.dll /t:exe Test.cs
27. oktober 2004 - 20:42
#8
Grundlæggende ser det jo fint ud... jeg ville måske vælge at lave en FactoryMethod i din .dll - istedet for at instantiere objekterne direkte fra Client.exe
27. oktober 2004 - 20:44
#9
Test.cs kan faktisk laves simplere med den CreateInstance du har fundet: using System; using System.Reflection; class TestClass { public static void Test(string dllname, string classname, int v, int offset) { Assembly asm = Assembly.Load(dllname); object[] ctorcallargs = { v, offset }; A o = (A)asm.CreateInstance(classname, false, BindingFlags.Public | BindingFlags.Instance, null, ctorcallargs, null, null); o.Show(); } public static void Main(string[] args) { Test("C", "C", 1, 2); } }
27. oktober 2004 - 20:44
#10
Tester lige ;)
27. oktober 2004 - 20:45
#11
wisen> Der er sikkert en del der kan smukkeseres. Koden skal bare vise hvordan reflection kaldene kan laves. Indpakningen regner jeg med at nemezis selv sørger for.
27. oktober 2004 - 22:12
#12
og et svar såfremt du får det til at virke
02. november 2004 - 09:33
#13
Dit eksempel virker fint, men jeg kender kun stien til dll'en så jeg er nødt til at bruge LoadFrom, men så virker det af en eller anden grund ikke :/
02. november 2004 - 09:39
#14
Og lige lidt mere info for resten. Har prøvet en del på at få det til at virke, men den smider en FileNotFoundException. Virkelig underligt, for når jeg udskriver stien, og checker den i Explorer/Dos-prompt, så er den der????
02. november 2004 - 09:45
#15
Ups.. skrev vist noget forkert. Det er hvis jeg bruger Load, den failer; naturligvis, da jeg bruger stien og ikke assembly navnet. Men hvis jeg bruger LoadFrom failer den når jeg bruger CreateInstance med følgende exceptUnhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Driver.DriverConnectionFormatEx ception: Invalid file access type. at Driver.File.Setup(String argument) at Driver.Stream..ctor(String argument) at Driver.File..ctor(String argument) --- End of inner exception stack trace --- at System.Reflection.RuntimeConstructorInfo.InternalInvoke(BindingFlags invok eAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean isBinder Default) at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, B inder binder, Object[] parameters, CultureInfo culture) at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder bin der, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binde r binder, Object[] args, CultureInfo culture, Object[] activationAttributes) at System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreC ase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture , Object[] activationAttributes) at Driver.Loader.createInstance(Assembly assembly, String name, Object[] ctor callargs) at Driver.Loader.RequestStream(String connection) at Driver.Implementaion.Main(String[] args)ion:
02. november 2004 - 23:16
#16
Mystisk. Den her virker hos mig: using System; using System.Reflection; class TestClass { public static void Test(string filename, string classname, int v, int offset) { Assembly asm = Assembly.LoadFrom(filename); object[] ctorcallargs = { v, offset }; A o = (A)asm.CreateInstance(classname, false, BindingFlags.Public | BindingFlags.Instance, null, ctorcallargs, null, null); o.Show(); } public static void Main(string[] args) { Test(@"C:\E\C.dll", "C", 1, 2); } }
02. november 2004 - 23:29
#17
Har fundet ud af det :) Det er for createInstance åbenbart pakker exceptions smidt i constructoren i en System.Reflection.TargetInvocationException så den ikke blev fanget af mine catch blokke... Meget underligt men jo egenlig fint nok.. hvis man altså lige ved det :) Point til dig arne_v
02. november 2004 - 23:29
#18
for = fordi ..?
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.