Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
IL.Emit mehrdimensionale array Property
Nokinger
myCSharp.de - Member



Dabei seit:
Beiträge: 48
Herkunft: Karlsruhe

Themenstarter:

IL.Emit mehrdimensionale array Property

beantworten | zitieren | melden

Hallo,

ich habe mir etwas geschrieben das zur Laufzeit eine Implementierung eines Interfaces mithilfe von Reflection Emit erstellt. Das ganze funktioniert auch wunderbar mit der Ausnahme das mehrdimensionale arrays nicht funktionieren. Eindiemnsionale Arrays dagegen gehen wunderbar.

void GenerateDataVarGetter(Type interfaceType,TypeBuilder builder, PropertyInfo property)
{
	MethodInfo getMethod = property.GetGetMethod();
	if (getMethod == null)
		return;

	const MethodAttributes attributes = MethodAttributes.Public |  MethodAttributes.Virtual |
		MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.SpecialName;

	Type t = property.PropertyType;
	MethodInfo baseMethod = typeof(DynamicStubClass).GetMethod("GetValue",BindingFlags.NonPublic | BindingFlags.Instance).MakeGenericMethod(t);

//Die baseMethod sieht wie folgt aus (exemplarische darstellung):
// public T GetValue<T>(string propName)
// {
//      ...
//      return (T)value;
//  }
//Diese Methode wird in der Basis Klasse DynamicStubClass Implementiert.
//Jeder Typ den ich zur laufzeit erstelle wird von dieser Basis Klasse //abgeleitet und Implementiert eben das interface für das zur laufzeit eine //Klasse erstellt werden soll

	string methodName = string.Format("{0}.{1}", interfaceType.Name, getMethod.Name);
	MethodBuilder method = builder.DefineMethod(methodName, attributes, t, Type.EmptyTypes);

	string propertyName = string.Format("{0}.{1}", interfaceType.Name, property.Name);
	PropertyBuilder propertyBuilder = builder.DefineProperty(propertyName, PropertyAttributes.None, t, null);
	
	ILGenerator il = method.GetILGenerator();
	il.Emit(OpCodes.Ldarg_0);
	il.Emit(OpCodes.Ldstr, property.Name); //string parameter für die baseMethod
	il.Emit(OpCodes.Callvirt, baseMethod);
	il.Emit(OpCodes.Ret);

	builder.DefineMethodOverride(method, getMethod);
	propertyBuilder.SetGetMethod(method);
}

Gegeben ist folgendes Interface:


public interface TestInterface
{
     IDataVar<short>[,] TestProperty {get;}
}

beim erstellen des Types also mit:

TypeBuilder.CreateType()

Erhalte ich folgende Fehlermeldung:
Fehler
Die Signatur für den Text und die Deklaration in einer Methodenimplementierung stimmen nicht überein

Wenn ich den MethodOverride auskommentiere...

//buider.DefineMethodeOverride(method,getMethod
...und den Methodennamen Impliziet anstatt Explizit festlege erhalte ich folgende Fehlermeldung:
Fehler
Die Methode "get_TestProperty() im Typ "XYZ" der Assembly "XYZ" hat keine Implementierung

Jedoch wenn ich die Property im Interface in ein Eindimensionales Array um deklariere, funktioniert alles einwandfrei.

Kann mir da jemand helfen?
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Nokinger am .
private Nachricht | Beiträge des Benutzers
Robin0
myCSharp.de - Member



Dabei seit:
Beiträge: 213

beantworten | zitieren | melden

Genaugenommen kannst du nur methoden in einem interface definieren.

bedeutet:

 
IDataVar<short>[,] TestProperty {get;}

Entspricht


[HideBySig]
[SpecialName]
public IDataVar<short>[,] get_TestProperty();

Und genau so solltest du die Methode dann auch definieren

Bsp:


String _propertyName = "Test";
Type _propertyType = typeof(IDataVar<short>[,]);
            PropertyBuilder propertyBuilder = _tb.DefineProperty(_propertyName, PropertyAttributes.HasDefault, _propertyType, null);

            #region get
            MethodBuilder getPropMthdBldr = _tb.DefineMethod("get_" + _propertyName,
                MethodAttributes.Public |
                MethodAttributes.SpecialName |
                MethodAttributes.HideBySig
                , _propertyType, Type.EmptyTypes);
//Edit //-->hier deine GetValue methode aufrufen
            getIl.Emit(OpCodes.Ldarg_0);
            getIl.Emit(OpCodes.Ldfld, fieldBuilder);
            getIl.Emit(OpCodes.Ret);
#endregion
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Robin0 am .
private Nachricht | Beiträge des Benutzers
Nokinger
myCSharp.de - Member



Dabei seit:
Beiträge: 48
Herkunft: Karlsruhe

Themenstarter:

beantworten | zitieren | melden

Hallo Robin0,

an der Signatur an sich konnte es nicht liegen, da ja nicht Arrays und Eindimensionale Arrays wunderbar funktioniert haben.

Jedoch bin ich gerade auf einen Interessanten Beitrag bei Microsoft gestoßen
KB960240: PRB: .NET Multidimensional arrays emitted by Reflection do not match compiled arrays

Darin wird beschrieben das dass Emitten von mehrdimensionalen Arrays noch einen Bug hatte, welcher erst mit dem Framework 4 scheinbar behoben wurde.

Ich habe das ganze auch getestet ... mit Framework 4 funktioniert das ganze tatsächlich :-)

Nun muss ich mit dem Kooperationspartner Sprechen ob es für ihn ein Problem ist wenn wir auf das Framework 4.0 Umstellen. Da wir im Anlagenbau sind und dort die Softwareverteilung manchmal etwas Schwieriger ist... aber das bekomme ich dann auch noch hin.

Trotzdem danke für dein Feedback!
private Nachricht | Beiträge des Benutzers