Tjo... Lägg till den som reference i projectet istället då... Det kan jag inte göra, då programmet använder massa olika Dller dynamiskt. Jag antar att vad du försöker göra är att anropa en .NET komponent från VB6. Namespace ChrGen3_CoreRules Vi utgår ifrån att du har kört gacutil och har nu din assemblyu i Global Assembly Cachen. danke. Class1 = Namnet på din klass. Eftersom din fråga gällde CreateObject och du fick fel 429 så antog jag att du använda VB6 och inte VB.NET som klient. Jag kör mest C# själv (annat än i demosyfte) och trodde inte att CreateObject fanns som kommando i VB.NET. Okey. Fick det inte att funka. Du får ut ditt objekt efter att du har kört CreateInstance, men det är bara av typen object vilket innebär att du inte kommer åt dina metoder etc om du inte gör en casting, men ska du göra en casting så måste du ha refernecer till din .dll och det ville du inte. Därför måste du använda dig av ett Type objekt för att kunna komma åt dina metodrar. Den heter Class1 =) hmm. Jag har detta överst i min class1 i Dll filen: Nu ser jag felet till varför det inte fungerar: hahah. Jag ger mig inte fören du får det att fungera :) Dim so As [String] = myAssembly.GetTypes()(0).ToString() Om du har kvar <System.Runtime.InteropServices.ProgId("Class1_NET.Class1")> så tabort det ur din dll för du behöver inte det attributet. svaret i so är: ChrGen3_CoreRules.Form1. Sälva konstruktorn är inte Public Class Class1 utan under Class Class1 ja, det finns en form i dll filen också. hmm, är du säker på att den dll:en som du läser in har klassen Class1? Dum fråga kanske.. vilket dilemma jag fick nu då. Du skriver: Min Class fanns listan, men så här såg det ut: ok, där ser man. okey. låt oss säga jag har en funktion som ser ut som sådan: Hela diskussionen rörde sig ju om att du inte ville ha en referens till ditt DLL... :-) För att vara extra snäll idag så hjälper jag dig med hur ett sådan kod kan se ut ;) alltså, med en referense menade jag mer att X ska peka på Class1 i min Dll. Va bra! Det du vill göra passar interface riktigt bra till, i kombination med mitt tips om att använda <probing> i config-fil. Vill bara infilka lite angående probing i configfilen. umm. som ni kanske redan märkt så verkar dessa koder ni ger mig vara litegranna utanför min kunskap. Du får skapa en ny assembly (dll) som har dina interface. Låt oss i detta exempel kalla den för minInterface.dll umm. okey... =)) *lite borta* Du lägger alla dina interface i en och samma dll, du behöver inte skapa en dll för varje interface det blir bara onödigt många filer som du säger. Alla andra dll:er som du gör refererar du till interface dll:en (Jag kallar den dll som har alla interface för interface dll:en). Denna dll ska även ditt klient program referera till för att veta om interfacen. det där med en vanlig Com DLL (vb6) verkade lättare... men fortfarande så kan jag inte använda mig utav references.Registrera Dlls. använda CreateObject
Jag vill kunna använda mig utav CreateObject() för att använda funktioner i min egna dll. Dll filen heter CoreRules.dll
Jag har testat halva dagen, men fortfarande inte fått det att funka.
jag har använt: >sn -k keyPair.snk<, för att skapa en nyckel.
sedan i AssemblyInfo.vb lagt till:
<Assembly: AssemblyKeyFileAttribute("sökväg...sgKey.snk")>
dll filen compileras utan fel.
har även gjort en: >regasm corerules.dll< utan fel.
och även testat mig utav; >gacutil /i corerules.dll<, men fortfarande så får jag samma fel av CreateObject(), "Cannot create ActiveX..."
error kod 429.
"ProgId not found or not supplied."
vad gör jag för fel... och hur ska det göras?
/ BlackWandSv: Registrera Dlls. använda CreateObject
Sv: Registrera Dlls. använda CreateObject
och ska klara av att det kan tillkomma nya Dll filer lite då och då.
annars hade jag ju självklart haft dom i references...Sv: Registrera Dlls. använda CreateObject
Det enda som jag kan komma på som du skulle kunna göra fel på är att du inte har en default konstruktor, för att COM ska kunna skapa en komponent så måste det finnas en konstruktor utan argument.
Om din klass ser ut som nedan så kommer inte COM kunna skapa en instans. Detta pga den konstruktor som definieras ersätter default konstruktorn, om man ej har någon konstruktor alls så kommer en default konstruktor automatiskt genereras och allt funkar...
<code>
public class Class1
{
public Class1(string s)
{
}
public void X()
{
}
}
</code>
Hoppas detta hjälper!
/MattiasSv: Registrera Dlls. använda CreateObject
<System.Runtime.InteropServices.ProgId("Class1_NET.Class1")> Public Class Class1
så här ser den ut. och sedan kommer mina funktioner.
Det är både en .net dll, och skall anropas från en .net klient.
vad jag vet, så har jag ju ingen konstruktor där.
och har även testat med bara Public Class Class1. funkar ändå inte.
och en annan sak som är krånglig är, hur reggar jag komponenten?
jag kör RegAsm corerules.dll
och har:
<Assembly: AssemblyKeyFileAttribute("D:\Mina Dokument\Programmering\Visual Basic .NET\Character Generator 3.NET\CoreRules\sgKey.snk")>
in min assembly fil för corerules.dll
jag hittar inget på KB på MS sida heller, där har dom bara sitt jädra office som exempel =P
/ RobbanSv: Registrera Dlls. använda CreateObject
Det finns nu flera alternativ att dynamiskt skapa klasser i .Net. Tex med Assemlby.LoadWithPartialName, Assembly.Load eller tex Activator.CreateInstanceAndUnWarp. Det finns flera sätt att göra det på.
Här har du ett exempel på hur du kan göra med LoadByPartialName, där vi har namespacet ChrGen3_CoreRules och klassen du ska använda dig av heter Class1 och din dll hetter ChrGen3_CoreRules.dll. Tänk på att om detta ska fungera så måste du ha en refenrece till din dll. Om du ska slippa detta så måste du tex använda dig av Type objektet och göra InvokeMember etc. Lite mer kodande.
<code>
Dim myAssembly As [Assemlby]
Dim myObject As Class1
myAssmbly = [Assembly].LoadWithPartialName("ChrGen3_CoreRules")
myObject = CType(myAssembly.CreateInstance, Class1)("ChrGen3_CoreRules.Class1")
</code>
Obs! Om du använder LoadWithPartialName så kommer den alltid att ta den senaste versionen av din assembly. Om du vill ha versionshantering och ladda en assembly med en viss version så använd Load istället.
Hoppas detta löser ditt problem.
/Fredrik NSv: Registrera Dlls. använda CreateObject
jag vill inte, och kan inte använda mig utav någon reference.
då dll filerna används dynamiskt, och ska kunna läggas till dynamiskt också.
umm alltså, jag vill ha X som en reference till Class1 i dll filen. jag antar det ska vara ett Object, inte en Type.
Och Dim object as Class1, vad är det för någe?
------------
Dim myObject As Object = CreateInstanceFrom(GetFixedPath(DllPath) & DllName, "ChrGen3_CoreRules.Class1").Unwrap()
denna rad borde funka, men om jag steppar, så hoppar den liksom över raden, den fortsätter aldrig på raden efter, utan jag kommer in i Form_resize.
jag har bara probs med detta =)Sv: Registrera Dlls. använda CreateObject
Om du ska använda dig av metoder och klasser utan referencer så måste du använda dig av InvokeMember.
Tex du kan göra följande:
<code>
Dim myAssembly As [Assemlby]
Dim myType as Type
Dim myObject As Object
myAssmbly = [Assembly].LoadWithPartialName("ChrGen3_CoreRules")
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Class1")
myType = myObject.GetType()
Dim s As [String] = CType(myType.InvokeMember("ToString", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, myObject, Nothing), [String])
</code>
Du behöver inte använda LoadWithPartial.... utan du kan använda CreateInstanceFrom och ange sökvägen till dll:en, bara du får ut ett initierat objekt som du sedan tar GetType på.
/Fredrik NSv: Registrera Dlls. använda CreateObject
Men om du som du säger har .NET DLLs och .NET klient så förstår jag inte alls varför du skulle hålla på med CreateObject, regasm, och System.Runtime.InteropServices.ProgId. Detta är COM relaterade teknologier och om man inte måste ha med COM i ekvationen så ska man nog undvika det. Tala om att komplicera saker och ting!
Den kod som Fredrik skickade i sitt senaste inlägg är ju klar för användning för dynamiska anrop. Men du verkar fortfarande ha problem att kunna ladda in dll i minnet. Det enklaste sättet att testa om din kod funkar är väl att stoppa in det refererade dllet i samma katalog som din applikation, så kommer .NET runtime definitivt hitta ditt dll.
När du sedan ska göra detta på riktigt så måste du tänka på att .NET ska hitta ditt dll. Ett sätt är att, som du redan insett, lägga dll i gac. Men personligen förstår jag inte varför man vill göra det. gac är ju bara registry igen, fast med multi-version support (vilket faktiskt fanns även i registry/com fast ingen använde sig av det...).
Ett annat alternativ är att använda .config för att speca vilka kataloger som .NET ska leta dller i.
<code>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="bin;bin2\subbin;bin3"/>
</assemblyBinding>
</runtime>
</configuration>
</code>
/MattiasSv: Registrera Dlls. använda CreateObject
Men, av vad jag förstått, så är det ett object jag vill ha, inte en type.
jag vill ju att X ska länka till Class1 i min Dll. Då är det väl ett object jag ska returnera?
Så vad är: myType = myObject.GetType() ?Sv: Registrera Dlls. använda CreateObject
Detta är vad jag har nu:
Dim myAssembly As [Assembly]
Dim myType As Type
Dim myObject As Object
'myAssembly = [Assembly].LoadWithPartialName("ChrGen3_CoreRules")
myAssembly = [Assembly].LoadFrom(GetFixedPath(DllPath) & DllName)
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Class1")
myType = myObject.GetType()
Dim s As [String] = CType(myType.InvokeMember("ToString", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, myObject, Nothing), [String])
Return myObject
'----------------------------
assembly.loadfrom, verkar funka då det tar tid, och Myassembly ändras från nothing till system.reflection.
men myObject kvarstår som nothing.
och vad gör den där 's' strängen ovan?
och jag har även testat många andra sätt, då hoppar de´n bara ur denna funktion, och fortsätter i form_resize, som inte ens är den funktion som skulle komma efter denna!?!
Och som Mattias sade, det vore bra om man inte behövde registrera dom och sånt.
alla Dll filer ligger i olika kataloger under huvudkatalogen, så jag kör med hela sökvägen.
Och som mattias även sade, Createobject är för Com object, vilket .net inte är.
jag är ute efter ett sätt som kan göra så att objectet X länkas till Class1 i en angiven dll. det är vad jag är ute efter. och varför ska det vara så jädra krångligt? =)Sv: Registrera Dlls. använda CreateObject
Du behöver inte regga dina dll:er, du kan ha dom under din root mapp i underliggande mappar och gör komma åt dom via tex LoadFrom eller som Mattias skrev ange i configurationsfilen vart den ska leta efter dll:erna.
Att CreateIntance returnerar nothing kanske beror på att din klass i din assembly inte heter Class1 utan att du har ett annat namn på klassen. Ersätt Class1 men det namn du har satt på din klass.
/Fredrik NSv: Registrera Dlls. använda CreateObject
okey. så Type är vad jag måste ha, då vet jag det iaf.
men vore inte helt fel om myObject ville bli något också!?! =)Sv: Registrera Dlls. använda CreateObject
Testa och byt ut
<code>
myAssembly = [Assembly].LoadFrom(GetFixedPath(DllPath) & DllName)
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Class1")
</code>
till:
<code>
myObject = AppDomain.CreateInstanceFromAndUnwrap(
GetFixedPath(DllPath) & DllName, "ChrGen3_CoreRules.Class1" )
</code>
Har du namespacet ChrGen3_CoreRules på den dll du vill läsa?
Om inte så byta ut ChrGen3_CoreRules.Class1 till ditt namespace + namnet på din klass (namespace.classname). För om du for myObject att bli Nothing så beror det på att den inte hittar den typ som du har angivit i den laddade dll:en.
/Fredrik NSv: Registrera Dlls. använda CreateObject
Namespace ChrGen3_CoreRules.Class1
Public Class Class1
...
...
end public
end namespace
'-------------
myObject = CreateInstanceFrom(GetFixedPath(DllPath) & _ DllName, "ChrGen3_CoreRules.Class1").Unwrap
myType = myObject.GetType()
jag tog instancefrom, för det andra fanna inte, såvida inte jag måste importera appdomain. och så tog jag .unwrap i slutet.
men vad som händer när jag kommer till denna rad, men f8, så precis när den har kört raden, så kommer jag inte till raden efter som jag borde, utan jag kommer till Form_resize !?! =)
På detta sätt vi gör nu, så krävs det ingen registreing av Dll va?
bäst jag frågar så vi inte sitter och krånglar i onödan. iof så är Dll filen reggad med RegAsm, men inte med GacUtil.
Väldigt tack för din hjälp iaf... fast vi verkar inte komma framåt =(
vet inte om det är jag som gör fel eller inte. men jag antar att dom exempel du gett mig är beprövade så att säga, och borde funka. men, ack, inte för mig =)Sv: Registrera Dlls. använda CreateObject
du har ett namespace som heter: ChrGen3_CoreRules.Class1 och en klass som heter Class1
För att få CreateInstance att hitta din class1 så måste du ange ditt namespace + klassnamn som jag har skrivit tidigare. Så din kod ska alltså se ut så här:
<code>
myObject = CreateInstanceFrom(GetFixedPath(DllPath) & _ DllName, "ChrGen3_CoreRules.Class1.Class1").Unwrap
myType = myObject.GetType()
</code>
/Fredrik N
ps.
Ett design tips är att du ändra ditt namespace till:
ChrGen3_CoreRules iställer för: ChrGen3_CoreRules.Class1.
Detta för att du inte ska få en typ som heter:
ChrGen3_CoreRules.Class1.Class1Sv: Registrera Dlls. använda CreateObject
mitt namespace har hade inte .class1 i slutet innan.
jag missförstod en av dina förklaringar, jag uppfattade det som om att jag skulle ha:
ChrGen3_CoreRUles.class1 i mitt namespeace.
alltså. jag hade bara ChrGen3_CoreRules innan, men har, som sagt, inte funkat då heller.
btw, är det någe fel på pellesoft, helt plötsligt så är min "mina inlägg" listan helt tom.Sv: Registrera Dlls. använda CreateObject
Så här gör vi. Strunt i att skapa en key till din assembly, låt den bara vara som den var från första början, inget regasm etc. Kompilera den och lägg den.
Skriv sedan i din klient kod detta:
(Se till så att GetFixedPath(DllPath) ger dig sökvägen till klintens bin mapp).
<code>
Dim myAssembly As [Assemlby]
Dim myType as Type
Dim myObject As Object
myAssembly = [Assembly].LoadFrom(GetFixedPath(DllPath) & _ DllName)
'Sätt en break point här och se om as innehållet namnet på din assemlby.
'Om så är vi på rätt väg.
Dim as As [String] = myAssemlby.ToString()
'Se om sa innehållet ditt namespace och class namn. Får du ett fel här
'så har vi inte lyckats hitta någon klass under din assembly
'då har vi något annat problem.
'Men går allt brå så ska myObject nedan inte vara nothing.
Dim so As [String] = myAssemlby.GetTypes()(0).ToString()
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Class1")
myType = myObject.GetType()
'Se om s innhåller något värde.
Dim s As [String] = CType(myType.InvokeMember("ToString", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, myObject, Nothing), [String])
</code>
OBS! Testa den kod jag skrev ovan utan att ändra så mkt. Se bara till att namespacet och klassens är rätt och att sökvägen till dll:en pekar rätt.
Angående Pellesoft så har jag märkt att vissa av mina inlägg försvinner bara. Vet inte varför, ev att sessionen har fått en timeout eller att inläggen har readerast manuelt.
Eller så är det en bugg.
/Fredrik NSv: Registrera Dlls. använda CreateObject
här så innehåller so en fet sträng, med siffror och mitt namn på Dll filen. så långt så bra.
men raden under:
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Class1")
så är myObject fortfarande nothing...
en fråga där också. Min dll fil heter CoreRules.dll, och namespace heter ChrGen3_Corerules.
i raden ovan ska det stå namespace.class1 antar jag, vilket det gör, men så det inte ska stå dll_filename.class1 ?
tack för hjälpen... fattar bara inte varför det ska va så krångligt =)
men även om det blir en time out för dig, så ska ju inte hela MIN 'mina inlägg' lista tömmas....
jag hade kanske 7-10 inlägg, nu är listan totalt tom... men men det har inget med det här att göra iofs =)Sv: Registrera Dlls. använda CreateObject
Se till att du har en default konstruktor som en nämnde ovan:
public Class1()
För det kan vara att du inte har en default konstruktor som gör så att din klass inte vill hittas.
Om detta inte hjälper så kan du väl vara snäll och skicka med din Class1 så jag kan se hur den ser ut, obs!, du behöver inte ta med allt bara jag får se huvudet och dina konstruktors.
I koden jag skickade ändra:
<code>
Dim so As [String] = myAssemlby.GetTypes()(0).ToString()
</code>
till
<code>
Dim so As [String] = myAssemlby.GetTypes()(0).FullName
</code>
Och se vas so innehåller nu, skriv gänra in värdet i detta forumet så jag ser vad du får för resultat.
Angående försvinnande foruminlägg, jag menade inte att dina försvinner för att jag sår en time out, utan att det ev kan bero på att du får det. Men då ska ju inte alla dina inlägg försvinna. Ev så är det någon som raderar dom eller så är det en bugg.
/Fredrik NSv: Registrera Dlls. använda CreateObject
och min header på Class filen ser ut så här:
Option Strict Off
Option Explicit On
Namespace ChrGen3_CoreRules
Public Class Class1
.... (kod)
så det ser nog inte ut som om jag har en konstruktor...
väl därför den väljer min form istället för class...
jag testade skriva Class1(), men då blev de fel på ().Sv: Registrera Dlls. använda CreateObject
Ska det finnas en typ en Public Class1().
Namespace ChrGen3_CoreRules
Public Class Class1
Public Class1()
Din dll innehåller ett Windows Form (Form1). Är det så att du har både klasser och Windows Forms objekt i din dll? Eller är din sökväg till dll:en till din applikations .exe fil? Alltså att du har skrivit in fel sökväg?
Om du är säker på att det är rätt dll så kan vi göra ett enkelt test.
GetTypes i myAssemlby.GetTypes() returnerar en array av Typer.
Gå genom dessa typer och skriv ut dess FullName propery och se om din Class1 listas.
/Fredrik NSv: Registrera Dlls. använda CreateObject
där har jag några picture controls med bilder i, bilder som är specifica för det Dll filen gör.
Umm. jag gjorde så här:
dim s2 as type = myassembly.gettype()
For I = 0 to ubound(s2)
msgbox s2(i)
next I
men när den ska köra igång msgbox, så ploppar jag iväg. jag hamnar där jag brukar hamna, i form_resize, för min start form.
Och det konstiga är att s2 innehöll 9 element. men körde inget, kom bara till den första sedan hoppade den, och sket i dom andra 8.
när jag tänker efter så verkar det hända så med alla rader som innehåller en:
Dim x as type = xyz.
Dim so As [String] = myAssembly.GetTypes()(0).FullName
returnerar Form1, som sagt. 1 module1, 2 module2, och några av dom andra returnerar mina structures i module2.
jag lade till en Public CLass1() i dll filen, skapade dll filen på nytt. men fortfarande så blir MyObject nothing...Sv: Registrera Dlls. använda CreateObject
Vad får du ut när du gör:
dim s2 as type = myassembly.gettype()
For I = 0 to ubound(s2)
msgbox s2(i).FullName '<--- FullName
next I
Se om den hittar din Class1 där, om inte så är det troligtvis fel dll som du läser in.
/Fredrik NSv: Registrera Dlls. använda CreateObject
GetTypes vägrar returnera till en array; s2() as type.
så sätter jag som du gjorde s2 as type = gettypes()
så tar den inte ubound(s2), då den inte är en array.
så då skippar den For loopen om jag kör programmet ändå, pga build errors där.
Min Class1 är sparad som Class1.vb.
har; Public Class Class1.
det är väl raden ovan som bestämmer vad den ska heta antar jag?
då det inte finns någe Name i properties för Class filen...Sv: Registrera Dlls. använda CreateObject
dim s2 as type() = myassembly.gettypes()
inte:
dim s2 as type = myassembly.gettypes()
Den kod du fick av mig klippte jag från dig och bara gjorde den änringen med FullName tänkte inte på att du gjorde en GetType.
/Fredrik NSv: Registrera Dlls. använda CreateObject
ChrGen_Corerules.ChrGen3_CoreRules.Class1
den ena måste ju vara mitt namespace, men vart kommer den andra ifrån?
Den andre kanske kommer från project properties. där i build inställningarna.
jag testade ta bort mitt namespace i dll filen, då blev det ChrGen3_CoreRules.Class1.
så nu fungerade:
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Class1")
och Mytype = xyz fungerade.
men dim s as string = xyz blev fel. då den hoppade.
men jag tror vi kan strunta i den.
Så nu tror jag det fungerar, men hur använder jag denna nu då?
jag har ju denna i en function GetMyDllObject()
den ska då returnera Class1 (filen), ska jag returnera objectet eller typen (myobject/mytype) ?
och kan jag då skriva X (det som fick return värdet); X.minFunktion() ?Sv: Registrera Dlls. använda CreateObject
Du kan tyvärr inte skriva typ: X.dinFunktion() eftersom x är object.
Eftersom du inte har några referencer till din dll.
Du måste använda dig av InvokeMember för att köra din metodrar
Denna kör en ToString() på ditt objekt:
<code>
Dim s As [String] = CType(myType.InvokeMember("ToString", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, myObject, Nothing), [String])
</code>
Problemet här är att om du nu ska köra en metod som returnerar en klass som du inte har referenser till så går det inte, eller jo det går men då blir det object och för att då köra metodrar eller annat så måste du även där använda InvokeMemeber.
Som jag skrev bland dom första svaren på dina frågor är just att ska man göra detta dynamiskt så krävs det mkt kodande.
/Fredrik NSv: Registrera Dlls. använda CreateObject
function GetBonus(Level as integer) as string()
....
end function
så för att skicka med level 6 i functionen så skriver jag då:
ummm. hur? =)
och den där jätte långa raden, måste hela den användas för varje funktion/sub i min dll? det blri ju fett mycket kod.
det går inte på något sätt att få X att referera till min dll, som det gjorde i vb6 med CreateObject() ?Sv: Registrera Dlls. använda CreateObject
Om du, vilket du indikerar eftersom du vill vara helt dynamisk, vill kunna anrop vilka metoder som helst i vilket DLL som helst så måste du göra dessa långa anrop. Och inte nog med det, du måste dynamiskt bygga upp dem eftersom de är beroende på hur metodens signatur ser ut. I så fall kommer du antagligen ha användning av klasserna som finns i System.Reflection.
Om du vet hur metoderna ser ut så kan du hårdkoda dem, men enklare skulle i så fall vara att skapa ett interface och låta alla komponenter implementera detta. Då skulle du kunna få skriva kod som "X.minFunktion()" eftersom interfacet är känt hos klienten och implementerat hos komponenten. Detta vore ju faktiskt snyggast, men funkar inte om du vill kunna anropa valfri metod i valfri komponent.
För att skicka med 6 till en funktion måste du skicka med en paramter istället för ett av Nothing params. Kolla i hjälpen för .NET Framework SDK för Type.InvokeMember, där finns kompletta exempel.
/MattiasSv: Registrera Dlls. använda CreateObject
Du kan anropa din GetBonus på detta sätt:
<code>
Dim v As Int32 = CType(myType.InvokeMember("GetBonus", BindingFlags.DeclaredOnly Or BindingFlags.Public Or BindingFlags.NonPublic Or BindingFlags.Instance Or BindingFlags.InvokeMethod, Nothing, myObject, New [Object]() {6}), Int32)
</code>
Följ gärna Mattias råd.
/Fredrik NSv: Registrera Dlls. använda CreateObject
nu ska jag förklara hur det här fungerar, och hur jag vill kunna göra =)
Låt oss säga jag har massa Dll filer för Lastbilar, och Flygplan.
alla Lastbils Dll funktioner ser likadana ut. alltså funktionerna är inte dynamiska.
Och även Flygplanens funktioer har samma uppbyggnad.
Men när självaste huvudprogrammet är kompilerat. så ska bara programmet läsa in alla Dll filer i mapparna Flygplan och Lastbilar, när dom behövs, tex då man väljer Lastbil 5 i en lista.
Jag vet alltid vart och när, och vad funktionerna heter. så det behöver inte vara dynamiskt.
bara det att jag kan få X att peka mot den Dll jag vill just då jag vill det.
alla flygplan har en egen Form, så jag, som programmerare, vet vilken funktion som ska fungera när och hur.
Som tex, om jag sätter X till Flygplan 6, så frågar jag tex efter GetPlaneSpeed().
men i en annan Form så sätts X till Lastbil, och då kör jag GetSpeed().
så det enda jag behöver är ett LÄTT sätt att få X att peka på min Class1 fil i Dll filerna.
Och LÄTT kunna komma åt dom funktioner som finns, HELST utan rader som består av 2000 tecken.
alltså. om Dll filerna behöver registreras för att få det att funka som jag menar, så är det OK. bara jag kan koppa X till Class1 filen.
Som i VB6, CreateObject("ChrGen3_CoreRules.Class1") Done!
X.bla()
dom kan ju liksom inte varit så dumma så att dom gjort det hundra gånger krångligare än detta?
eller det kanske beror på för att i .NET så är Dll filerna normala, inte ActiveX ?
För den där feta raden ser lite väl fet ut för att göra det jag vill, helt onödigt fet ut liksom.
om det ska vara så dåligt gjort, så går jag nog hellre tillbaka till vb6 igen. =(Sv: Registrera Dlls. använda CreateObject
Du skapar ett interface för Lastbilar, ett för Flygplan, etc. och implementerar lämpligt interface i varje klass. Nedan är en på frihand skriven kod, jag skriver C# vanligtvis så det kan vara lite sådär med syntax, men du fattar nog.
<code>
Interface IFlygplan
Function GetPlaneSpeed() As Integer
... andra funktioner eller metoder
End Interface
Class Cessna
Implements IFlygplan
Function GetPlaneSpeed() As Integer Implements Flygplan.GetPlaneSpeed
...
End Function
End Class
</code>
Koden för anrop blir då ungefär som nedan:
<code>
' Skapa objektet
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Cessna")
' Cessna är ett flygplan, så behandla det som det!
Dim flyg As IFlygplan = myObject ' Osäker på syntax för att göra detta i VB.NET
' Anropa funktionen med early binding
myRes = flyg.GetPlaneSpeed()
</code>
config-filen kan då innehålla:
<code>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="C:\MinaFlygplan;C:\MinaBilar"/>
</assemblyBinding>
</runtime>
</configuration>
</code>
Du skapar helt enkelt ett interface för varje typ av fordon och om du lägger dem i olika kataloger så kan du ju lätt veta om det är IFlygplan eller IBil som du ska jobba med.
Hoppas att detta hjälper!
/MattiasSv: Registrera Dlls. använda CreateObject
Att ange c:\MinaLastbilar etc kommer inte att fungera. privatePath kan bara vara underkataloger till där huvud applikationen ligger. Så skapa MinaFlygplan och MinaBilar som undermappar till din klientapplikation och skriv:
<code>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="MinaFlygplan;MinaBilar"/>
</assemblyBinding>
</runtime>
</configuration>
</code>
En kanske onödig sak men tar med detta ändå.
Denna kod:
<code>
' Skapa objektet
myObject = myAssembly.CreateInstance("ChrGen3_CoreRules.Cessna")
' Cessna är ett flygplan, så behandla det som det!
Dim flyg As IFlygplan = myObject ' Osäker på syntax för att göra detta i VB.NET
</code>
Kan skrivas om till tex:
<code>
' Skapa objektet
Dim myObject As IFlygplan = CType(myAssembly.CreateInstance("ChrGen3_CoreRules.Cessna"),IFlygplan)
</code>
/Fredrik NSv: Registrera Dlls. använda CreateObject
men om jag förstått det rätt så ska jag ha ett interface där jag har mina funktioner, metoder, och sedan samma funktioner och metoder i den riktiga classes?
fast jag antar att interface inte behöver någon kod... bara självaste funktionerna.
Dim myObject As IFlygplan = CType(myAssembly.CreateInstance("ChrGen3_CoreRules.Cessna"),IFlygplan)
och denna kod skulle jag anta det blir fel i om jag inte är helt borta.
men interfacet ligger i dll (class) filen. hur kan jag då Dimensionera något som IFLygplan, då det interfacet inte finns i huvudprogrammet.
och den där config-file antar jag är på huvudporgrammet. dum fråga iofs =)Sv: Registrera Dlls. använda CreateObject
Denna assembly kompilerar du och lägger under din klient mapp.
De andra assembly. FlygPlan, LastBil etc refererar till minInterface.dll, det gör även din klient.
minInterface
__ _______|______________
| | |
Klient LastBil Flygplan
Ex på hur koden skulle kunna se ut i de dll:er du vill läsa in dynamiskt.
<code>
Public Class Class1 Implements ILastBil
</code>
Här är överkurs för din del kanske:
Istället för att använda dig av ett interface så skulle du kunna skap bas klasser till dina flygplan och lastbilar som har de grundegenskaper ett flygplan och en lastbil har. På detta sätt får du en snyggare design och kan återanvända kod. Jag skulle starkt rekommendera dig köpa en bok om hur du bygger object orienterade applikationer i .Net.
Denna boken kanske kan vara något http://www.apress.com/book/bookDisplay.html?bID=90
har själv inte läst den men APress tycker jag gör många bra böcker.
Som sagt, skapa en gemensam dll som har interfacen för flygplan och lastbilar som både din klient refererar till och dina lastbilar och flygplans dll:er gör. På så sätt kan du utan problem lösa det du vill kunna göra eftersom alla dll:erna refererar till en gemensam dll som har de interface du använder dig av.
/Fredrik NSv: Registrera Dlls. använda CreateObject
nu snurrar det i bollen...
så jag har en INterface dll. som har funktioner med samma namn som funktionerna som Dll filerna har?
men alla Dll filer har inte samma funktions namn, eller funkar inte likadant om dom nu skulle ha samma namn. då blir det väl lite krångligt?
Dom olika Dll typerna som jag har är: Class(yrke), Race, Spells, Templates, Feats, och någon mer har jag för mig.
Alla funkar olika, så då måste jag ha ett interface för varje 'typ', rätt?
då har vi genast kommit upp o väldigt många Dll filer. iofs, funkar det vore det ju bra.
Så om jag skapar en interface dll för varje typ, och i varje dll har jag implements (interface dll). och i huvudprogrammet så har jag... vad?
Och när jag skriver implements Ixyz i Public Class Class1 .... så vet den vilken Dll den ska ta eller måste den Dll ha det namnet och ligga i samma mapp?
jag måste erkänna jag inte forskat mycket av det jag fått av er. just för att det snurrat i huvet.
Jag kan säga dig att snart slår jag fast att .net suger =))
Men jag har iaf nu fått det att funka mot Dll, och vet att jag kan använda Interface. så det är väl nog med hjälp. då är det bara att försöka få det att gå ihop, på något sätt...
det jag inte förstår är hur kopplingen mellan Interfaces och Implements, fungerar.
I min dll har jag:
Public Class Class1
implements Ixyz <- mitt interface.
Public Class()1 <- konstruktor
men hur hittas Ixyz då den ligger i en annn Dll? (interface Dll:n för alla Dlls av samma typ)
I exemplet som finns i .net så har dom Interfacet i Class filen, då är det ju inte så svårt att se hur det hela hänger ihop.
Och sedan i huvudprogrammet, ska jag koppla X mot Interface, eller mot (icke interface) Dll filen? jag antar Dll filen, men då, enligt mig, används ju inte Interface Dll áv huvudprogrammet... rätt?
Du sade att jag skulle referera både Dll filerna och klient programmet till Interfacet, men då använder jag ju inte den Dlls funktioner jag vill ha, utan dom som är tomma och finns i Interface...
Jag måste ha fel på detta =), det skulle jag iaf tro att jag har.
Och köpa bok vill jag inte, inte för ett (litet) problem.
Umm, en fråga... om jag skulle ha kvar Dll filerna i VB6, och bara ha klienten i .NET, skulle det göra saken lättare? tex, skulle CreateObject fungera rakt av, då dll filer i Vb6 är ActiveX.. ?Sv: Registrera Dlls. använda CreateObject
Du skapar ett interface för varje typ med de funktioner som de ska ha.
Dessa funktioner i respektive interface måste då finnas i respektive klass som använder sig av interfacen. Läs lite om Interface programmering i SDK:n tror det ska finnas lite saker om det så förstår du nog bättre sedan.
Du kan använda dig av gamla VB6 komponenter i .Net.
Du väljer bara att lägga till en refernes och väls COM och sedan pekar på din COM dll. Du använder sedan den på samma sätt som du använder vilken klass som helst i .Net. Alltså du behöver inte göra en CreateObjeckt utan det räcker att du använder New.
/Fredrik NSv: Registrera Dlls. använda CreateObject
men jag ska titta in mer i saken. nu har jag ju definitivt massa exempel att gå på.
ni har ju skickat in ett antal =).
och förklarat det säkerligen 3 ggr om.
så nu är det väl dags att jag slutar krypa, och börjar gå upprätt istället =)
men av vad jag förstår så ligger dett krångel i att .NET inte är Com Dlls.
och därför fungerar det inte bara att peka X mot Class1 med CreateObject.
jag ska nog ta och behålla Dll filerna i vb6 om jag får detta att funka.
Tack för eder hjälp.
Jag hör avmig om det inte funkar, vilket det inte lär göra.
(kan det gå fel, så gör det det också)