Laden...

IL.Emit mehrdimensionale array Property

Erstellt von Nokinger vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.431 Views
N
Nokinger Themenstarter:in
48 Beiträge seit 2010
vor 9 Jahren
IL.Emit mehrdimensionale array Property

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: > Fehlermeldung:

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: > Fehlermeldung:

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?

R
212 Beiträge seit 2012
vor 9 Jahren

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

N
Nokinger Themenstarter:in
48 Beiträge seit 2010
vor 9 Jahren

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!