public static Delegate CreateOnShouldListenToDelegate(Type activitySourceType, MethodInfo onShouldListenToMethodInfo) { var dynMethod = new DynamicMethod( "OnShouldListenToDyn", typeof(bool), new[] { activitySourceType }, typeof(ActivityListener).Module, true); var proxyResult = DuckType.GetOrCreateProxyType(typeof(IActivitySource), activitySourceType); var proxyType = proxyResult.ProxyType; if (proxyType is null) { ThrowHelper.ThrowNullReferenceException($"Resulting proxy type after ducktyping {activitySourceType} is null"); } var method = onShouldListenToMethodInfo.MakeGenericMethod(proxyType); var proxyTypeCtor = proxyType.GetConstructors()[0]; var il = dynMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Newobj, proxyTypeCtor); il.EmitCall(OpCodes.Call, method, null); il.Emit(OpCodes.Ret); return(dynMethod.CreateDelegate(typeof(Func <,>).MakeGenericType(activitySourceType, typeof(bool)))); }
static void Main(string[] args) { dynamic person = new { Name = "Peter" }; var p = DuckType.As <IPerson>(person); Console.WriteLine(p.Name); }
public int SubtractFromNumToSpawn(int num, DuckType unit) { num--; if (num <= 0) { if (unit == type[0]) { typeTemp.RemoveAt(0); } if (unit == type[1]) { typeTemp.RemoveAt(1); } if (unit == type[2]) { typeTemp.RemoveAt(2); } } if (typeTemp.Count == 0) { CancelInvoke("SpawnObject"); } return(num); }
public static MappedDiagnosticsContextSetterProxy GetMdcProxy(Assembly nlogAssembly) { var mdcType = nlogAssembly.GetType("NLog.MappedDiagnosticsContext"); if (mdcType is not null) { // NLog 2.0+ var createTypeResult = DuckType.GetOrCreateProxyType(typeof(MappedDiagnosticsContextSetterProxy), mdcType); if (createTypeResult.Success) { return(createTypeResult.CreateInstance <MappedDiagnosticsContextSetterProxy>(instance: null)); } } mdcType = nlogAssembly.GetType("NLog.MDC"); if (mdcType is not null) { // NLog 1.0+ var createTypeResult = DuckType.GetOrCreateProxyType(typeof(MappedDiagnosticsContextSetterProxy), mdcType); if (createTypeResult.Success) { return(createTypeResult.CreateInstance <MappedDiagnosticsContextSetterProxy>(instance: null)); } } return(null); }
public void Initialize() { Baz baz = new Baz(); foo = DuckType.Cast <Foo>(baz); Assert.AreNotSame(baz, foo); }
[Ignore] //Manual test public void As_Loop() { foreach (object obj in GetObjects()) { Assert.IsNotNull(DuckType.As <IHasValue>(obj).Value); } }
public void CastToImplementedType() { Baz baz = new Baz(); Foo foo = DuckType.Cast <Foo>(baz); Assert.AreSame(baz, foo); foo.Bar(); }
public IQuackable getDuck(DuckType duckType) { if (DuckDictionary.ContainsKey(duckType)) { return DuckDictionary[duckType]; } else return null; }
public void EmptyMethodNoReturnType() { Baz baz = new Baz(); Foo foo = DuckType.Cast <Foo>(baz); Assert.AreNotSame(baz, foo); foo.Bar(); }
public void As_Invalid() { string expected = Guid.NewGuid().ToString(); BespokeString bespoke = new BespokeString(expected); Assert.IsNotInstanceOfType(bespoke, typeof(IHasValue)); IHasValue duck = DuckType.As <IHasValue>(bespoke); Assert.IsNull(duck); }
public void OverloadTestSameReturnTypes() { Baz baz = new Baz(); Quux foo = DuckType.Cast <Quux>(baz); Assert.AreNotSame(baz, foo); Assert.AreEqual("Hello World!", foo.Qux("Hello World!")); Assert.AreEqual("2", foo.Qux(2)); }
public void ChangeType(DuckType duckType) { type = duckType; GetComponent <Attack>().type = type; GetComponent <Health>().type = type; GetComponent <Move>().type = type; GetComponent <SpriteRenderer>().sprite = type.sprite; }
public void As_Struct() { int expected = _random.Next(); BespokeInt bespoke = new BespokeInt(expected); Assert.IsNotInstanceOfType(bespoke, typeof(IHasValue)); IHasValue duck = DuckType.As <IHasValue>(bespoke); Assert.IsInstanceOfType(duck, typeof(IHasValue)); Assert.AreEqual(expected, duck.Value); }
public void As() { DateTime expected = new DateTime(_random.Next(1900, 2000), _random.Next(1, 12), _random.Next(1, 28)); BespokeDateTime bespoke = new BespokeDateTime(expected); Assert.IsNotInstanceOfType(bespoke, typeof(IHasValue)); IHasValue duck = DuckType.As <IHasValue>(bespoke); Assert.IsInstanceOfType(duck, typeof(IHasValue)); Assert.AreEqual(expected, duck.Value); }
public ExprDotMethodForgeNoDuck( string optionalStatementName, MethodInfo method, ExprForge[] parameters, DuckType type) { OptionalStatementName = optionalStatementName; Method = method; Parameters = parameters; this.type = type; }
public void TestMethodParameters() { Baz baz = new Baz(); Foo foo = DuckType.Cast <Foo>(baz); Assert.AreNotSame(baz, foo); foo.MethodString("test"); foo.MethodInt(1337); foo.MethodBool(true); foo.MethodLong(1); }
public void OverloadTestDifferentReturnTypes() { Baz baz = new Baz(); Foo foo = DuckType.Cast <Foo>(baz); Assert.AreNotSame(baz, foo); Assert.AreEqual("Hello World!", foo.Bar("Hello")); Assert.AreEqual(4, foo.Bar(2)); Assert.AreEqual(false, foo.Bar(true)); }
static DiagnosticObserverListener() { try { var diagnosticListenerType = Type.GetType("System.Diagnostics.DiagnosticListener, System.Diagnostics.DiagnosticSource"); if (diagnosticListenerType is null) { ThrowHelper.ThrowNullReferenceException("System.Diagnostics.DiagnosticListener cannot be found."); } var sourceProxyResult = DuckType.GetOrCreateProxyType(typeof(ISource), diagnosticListenerType); var sourceProxyResultProxyType = sourceProxyResult.ProxyType; if (sourceProxyResultProxyType is null) { ThrowHelper.ThrowNullReferenceException($"Resulting proxy type after ducktyping {diagnosticListenerType} is null"); } var onShouldListenToMethodInfo = typeof(ActivityListenerHandler).GetMethod(nameof(ActivityListenerHandler.OnShouldListenTo), BindingFlags.Static | BindingFlags.Public); if (onShouldListenToMethodInfo is null) { ThrowHelper.ThrowNullReferenceException("ActivityListenerHandler.OnShouldListenTo cannot be found."); } var onShouldListenToMethod = onShouldListenToMethodInfo.MakeGenericMethod(sourceProxyResultProxyType); var onShouldListenToResultMethodInfo = typeof(DiagnosticObserverListener).GetMethod(nameof(DiagnosticObserverListener.OnShouldListenToResult), BindingFlags.Static | BindingFlags.Public); if (onShouldListenToResultMethodInfo is null) { ThrowHelper.ThrowNullReferenceException("DiagnosticObserverListener.OnShouldListenToResult cannot be found."); } var onShouldListenToResultMethod = onShouldListenToResultMethodInfo.MakeGenericMethod(sourceProxyResultProxyType); // Create delegate for OnShouldListenTo<T> where T is Source var onShouldListenToDyn = new DynamicMethod("OnShouldListenToDyn", typeof(void), new[] { typeof(object) }, typeof(ActivityListener).Module, true); var sourceProxyResultProxyTypeCtor = sourceProxyResultProxyType.GetConstructors()[0]; var onShouldListenToDynIl = onShouldListenToDyn.GetILGenerator(); onShouldListenToDynIl.Emit(OpCodes.Ldarg_0); onShouldListenToDynIl.Emit(OpCodes.Newobj, sourceProxyResultProxyTypeCtor); onShouldListenToDynIl.Emit(OpCodes.Dup); onShouldListenToDynIl.EmitCall(OpCodes.Call, onShouldListenToMethod, null); onShouldListenToDynIl.EmitCall(OpCodes.Call, onShouldListenToResultMethod, null); onShouldListenToDynIl.Emit(OpCodes.Ret); OnShouldListenToDelegate = (Action <object>)onShouldListenToDyn.CreateDelegate(typeof(Action <object>)); } catch (Exception ex) { Log.Error(ex, "Error on DiagnosticObserverListener static constructor"); OnShouldListenToDelegate = o => { }; } }
public static bool DuckIs <T>(this object instance) { if (instance is null) { DuckTypeTargetObjectInstanceIsNull.Throw(); } if (DuckType.CreateCache <T> .IsVisible) { return(DuckType.CanCreate <T>(instance)); } return(false); }
public static bool DuckIs(this object instance, Type targetType) { if (instance is null) { DuckTypeTargetObjectInstanceIsNull.Throw(); } if (targetType != null && (targetType.IsPublic || targetType.IsNestedPublic)) { return(DuckType.CanCreate(targetType, instance)); } return(false); }
public static Duck GetDuck(DuckType muscovy) { switch (muscovy) { case DuckType.Muscovy: return(new MuscovyDuck()); case DuckType.Plastic: return(new PlasticDuck()); default: return(null); } }
public static object DuckAs(this object instance, Type targetType) { if (instance is null) { DuckTypeTargetObjectInstanceIsNull.Throw(); } if (targetType != null && (targetType.IsPublic || targetType.IsNestedPublic)) { DuckType.CreateTypeResult proxyResult = DuckType.GetOrCreateProxyType(targetType, instance.GetType()); if (proxyResult.Success) { return(proxyResult.CreateInstance(instance)); } } return(null); }
private static T ConvertType <T>(object value) { var conversionType = typeof(T); if (value is null || conversionType == typeof(object)) { return((T)value); } Type valueType = value.GetType(); if (valueType == conversionType || conversionType.IsAssignableFrom(valueType)) { return((T)value); } // Finally we try to duck type return(DuckType.Create <T>(value)); }
public static bool TryDuckCast(this object instance, Type targetType, out object value) { if (instance is null) { DuckTypeTargetObjectInstanceIsNull.Throw(); } if (targetType != null && (targetType.IsPublic || targetType.IsNestedPublic)) { DuckType.CreateTypeResult proxyResult = DuckType.GetOrCreateProxyType(targetType, instance.GetType()); if (proxyResult.Success) { value = proxyResult.CreateInstance(instance); return(true); } } value = default; return(false); }
public static Duck GetDuckByType(DuckType duckType) { switch (duckType) { case DuckType.RUBBER_DUCK: return(new Duck( new NoFlyer(), new MutedQuacker() )); case DuckType.FLYING_BUT_LOUD_DUCK: return(new Duck( new GoodFlyer(), new LoudQuacker() )); default: throw new Exception("There is no duck defined with the type: " + duckType.ToString()); } }
static DiagnosticSourceEventListener() { try { var activityType = Type.GetType("System.Diagnostics.Activity, System.Diagnostics.DiagnosticSource", throwOnError: true); var onNextActivityMethodInfo = typeof(DiagnosticSourceEventListener).GetMethod(nameof(DiagnosticSourceEventListener.OnNextActivity), BindingFlags.Static | BindingFlags.NonPublic); if (onNextActivityMethodInfo is null) { ThrowHelper.ThrowNullReferenceException("DiagnosticSourceEventListener.OnNextActivity cannot be found."); } // Create delegate for OnNext + Activity var onNextActivityDynMethod = new DynamicMethod("OnNextActivityDyn", typeof(void), new[] { typeof(string), typeof(KeyValuePair <string, object>), typeof(object) }, typeof(ActivityListener).Module, true); DuckType.CreateTypeResult onNextActivityProxyResult; if (activityType !.GetField("_traceId", DuckAttribute.DefaultFlags) is not null) { onNextActivityProxyResult = DuckType.GetOrCreateProxyType(typeof(IW3CActivity), activityType); } else { onNextActivityProxyResult = DuckType.GetOrCreateProxyType(typeof(IActivity), activityType); } var onNextActivityProxyResultProxyType = onNextActivityProxyResult.ProxyType; if (onNextActivityProxyResultProxyType is null) { ThrowHelper.ThrowNullReferenceException($"Resulting proxy type after ducktyping {activityType} is null"); } var onNextActivityMethod = onNextActivityMethodInfo.MakeGenericMethod(onNextActivityProxyResultProxyType); var onNextActivityProxyTypeCtor = onNextActivityProxyResultProxyType.GetConstructors()[0]; var onNextActivityDynMethodIl = onNextActivityDynMethod.GetILGenerator(); onNextActivityDynMethodIl.Emit(OpCodes.Ldarg_0); onNextActivityDynMethodIl.Emit(OpCodes.Ldarg_1); onNextActivityDynMethodIl.Emit(OpCodes.Ldarg_2); onNextActivityDynMethodIl.Emit(OpCodes.Newobj, onNextActivityProxyTypeCtor); onNextActivityDynMethodIl.EmitCall(OpCodes.Call, onNextActivityMethod, null); onNextActivityDynMethodIl.Emit(OpCodes.Ret); OnNextActivityDelegate = (Action <string, KeyValuePair <string, object>, object?>)onNextActivityDynMethod.CreateDelegate(typeof(Action <string, KeyValuePair <string, object>, object?>)); }
private void CheckDuckType() { if (rdbMallard.Checked) { _ducktype = DuckType.MallardDuck; } if (rdbRedHead.Checked) { _ducktype = DuckType.RedHeadDuck; } if (rdbRubber.Checked) { _ducktype = DuckType.RubberDuck; } if (rdbDecoyDuck.Checked) { _ducktype = DuckType.DecoyDuck; } switch (_ducktype) { case DuckType.MallardDuck: _duck = new MallardDuck(); break; case DuckType.RedHeadDuck: _duck = new RedHeadDuck(); break; case DuckType.RubberDuck: _duck = new RubberDuck(); break; case DuckType.DecoyDuck: _duck = new DecoyDuck(); break; } }
public static Delegate CreateOnActivityStoppedDelegate(Type activityType, MethodInfo onActivityStoppedMethodInfo) { var dynMethod = new DynamicMethod( "OnActivityStoppedDyn", typeof(void), new[] { activityType }, typeof(ActivityListener).Module, true); var activityProxyType = typeof(IActivity5); if (activityType.Assembly.GetName().Version?.Major >= 6) { activityProxyType = typeof(IActivity6); } var proxyResult = DuckType.GetOrCreateProxyType(activityProxyType, activityType); var proxyType = proxyResult.ProxyType; if (proxyType is null) { ThrowHelper.ThrowNullReferenceException($"Resulting proxy type after ducktyping {activityType} is null"); } var method = onActivityStoppedMethodInfo.MakeGenericMethod(proxyType); var proxyTypeCtor = proxyType.GetConstructors()[0]; var il = dynMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Newobj, proxyTypeCtor); il.EmitCall(OpCodes.Call, method, null); il.Emit(OpCodes.Ret); return(dynMethod.CreateDelegate(typeof(Action <>).MakeGenericType(activityType))); }
public bool IsA(DuckType type) { return Types[type].All(Properties.ContainsKey) && Inheritance[type].All(IsA); }
internal static DynamicMethod CreateEndMethodDelegate(Type integrationType, Type targetType, Type returnType) { /* * OnMethodEnd signatures with 3 or 4 parameters with 1 or 2 generics: * - CallTargetReturn<TReturn> OnMethodEnd<TTarget, TReturn>(TTarget instance, TReturn returnValue, Exception exception, CallTargetState state); * - CallTargetReturn<TReturn> OnMethodEnd<TTarget, TReturn>(TReturn returnValue, Exception exception, CallTargetState state); * - CallTargetReturn<[Type]> OnMethodEnd<TTarget>([Type] returnValue, Exception exception, CallTargetState state); * */ Logger.Debug($"Creating EndMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}, ReturnType={returnType.FullName}]"); var onMethodEndMethodInfo = integrationType.GetMethod(EndMethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (onMethodEndMethodInfo is null) { Logger.Debug($"'{EndMethodName}' method was not found in integration type: '{integrationType.FullName}'."); return(null); } if (onMethodEndMethodInfo.ReturnType.GetGenericTypeDefinition() != typeof(CallTargetReturn <>)) { throw new ArgumentException($"The return type of the method: {EndMethodName} in type: {integrationType.FullName} is not {nameof(CallTargetReturn)}"); } var genericArgumentsTypes = onMethodEndMethodInfo.GetGenericArguments(); if (genericArgumentsTypes.Length < 1 || genericArgumentsTypes.Length > 2) { throw new ArgumentException($"The method: {EndMethodName} in type: {integrationType.FullName} must have the generic type for the instance type."); } var onMethodEndParameters = onMethodEndMethodInfo.GetParameters(); if (onMethodEndParameters.Length < 3) { throw new ArgumentException($"The method: {EndMethodName} with {onMethodEndParameters.Length} parameters in type: {integrationType.FullName} has less parameters than required."); } else if (onMethodEndParameters.Length > 4) { throw new ArgumentException($"The method: {EndMethodName} with {onMethodEndParameters.Length} parameters in type: {integrationType.FullName} has more parameters than required."); } if (onMethodEndParameters[onMethodEndParameters.Length - 2].ParameterType != typeof(Exception)) { throw new ArgumentException($"The Exception type parameter of the method: {EndMethodName} in type: {integrationType.FullName} is missing."); } if (onMethodEndParameters[onMethodEndParameters.Length - 1].ParameterType != typeof(CallTargetState)) { throw new ArgumentException($"The CallTargetState type parameter of the method: {EndMethodName} in type: {integrationType.FullName} is missing."); } var callGenericTypes = new List <Type>(); var mustLoadInstance = onMethodEndParameters.Length == 4; var instanceGenericType = genericArgumentsTypes[0]; var instanceGenericConstraint = instanceGenericType.GetGenericParameterConstraints().FirstOrDefault(); Type instanceProxyType = null; if (instanceGenericConstraint != null) { var result = DuckType.GetOrCreateProxyType(instanceGenericConstraint, targetType); instanceProxyType = result.ProxyType; callGenericTypes.Add(instanceProxyType); } else { callGenericTypes.Add(targetType); } var returnParameterIndex = onMethodEndParameters.Length == 4 ? 1 : 0; var isAGenericReturnValue = onMethodEndParameters[returnParameterIndex].ParameterType.IsGenericParameter; Type returnValueGenericType = null; Type returnValueGenericConstraint = null; Type returnValueProxyType = null; if (isAGenericReturnValue) { returnValueGenericType = genericArgumentsTypes[1]; returnValueGenericConstraint = returnValueGenericType.GetGenericParameterConstraints().FirstOrDefault(); if (returnValueGenericConstraint != null) { var result = DuckType.GetOrCreateProxyType(returnValueGenericConstraint, returnType); returnValueProxyType = result.ProxyType; callGenericTypes.Add(returnValueProxyType); } else { callGenericTypes.Add(returnType); } } else if (onMethodEndParameters[returnParameterIndex].ParameterType != returnType) { throw new ArgumentException($"The ReturnValue type parameter of the method: {EndMethodName} in type: {integrationType.FullName} is invalid. [{onMethodEndParameters[returnParameterIndex].ParameterType} != {returnType}]"); } var callMethod = new DynamicMethod( $"{onMethodEndMethodInfo.DeclaringType.Name}.{onMethodEndMethodInfo.Name}.{targetType.Name}.{returnType.Name}", typeof(CallTargetReturn <>).MakeGenericType(returnType), new Type[] { targetType, returnType, typeof(Exception), typeof(CallTargetState) }, onMethodEndMethodInfo.Module, true); var ilWriter = callMethod.GetILGenerator(); // Load the instance if is needed if (mustLoadInstance) { ilWriter.Emit(OpCodes.Ldarg_0); if (instanceGenericConstraint != null) { WriteCreateNewProxyInstance(ilWriter, instanceProxyType, targetType); } } // Load the return value ilWriter.Emit(OpCodes.Ldarg_1); if (returnValueProxyType != null) { WriteCreateNewProxyInstance(ilWriter, returnValueProxyType, returnType); } // Load the exception ilWriter.Emit(OpCodes.Ldarg_2); // Load the state ilWriter.Emit(OpCodes.Ldarg_3); // Call Method onMethodEndMethodInfo = onMethodEndMethodInfo.MakeGenericMethod(callGenericTypes.ToArray()); ilWriter.EmitCall(OpCodes.Call, onMethodEndMethodInfo, null); // Unwrap return value proxy if (returnValueProxyType != null) { var unwrapReturnValue = UnwrapReturnValueMethodInfo.MakeGenericMethod(returnValueProxyType, returnType); ilWriter.EmitCall(OpCodes.Call, unwrapReturnValue, null); } ilWriter.Emit(OpCodes.Ret); Logger.Debug($"Created EndMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}, ReturnType={returnType.FullName}]"); return(callMethod); }
internal static DynamicMethod CreateEndMethodDelegate(Type integrationType, Type targetType) { /* * OnMethodEnd signatures with 2 or 3 parameters with 1 generics: * - CallTargetReturn OnMethodEnd<TTarget>(TTarget instance, Exception exception, CallTargetState state); * - CallTargetReturn OnMethodEnd<TTarget>(Exception exception, CallTargetState state); * */ Logger.Debug($"Creating EndMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}]"); var onMethodEndMethodInfo = integrationType.GetMethod(EndMethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (onMethodEndMethodInfo is null) { Logger.Debug($"'{EndMethodName}' method was not found in integration type: '{integrationType.FullName}'."); return(null); } if (onMethodEndMethodInfo.ReturnType != typeof(CallTargetReturn)) { throw new ArgumentException($"The return type of the method: {EndMethodName} in type: {integrationType.FullName} is not {nameof(CallTargetReturn)}"); } var genericArgumentsTypes = onMethodEndMethodInfo.GetGenericArguments(); if (genericArgumentsTypes.Length != 1) { throw new ArgumentException($"The method: {EndMethodName} in type: {integrationType.FullName} must have a single generic type for the instance type."); } var onMethodEndParameters = onMethodEndMethodInfo.GetParameters(); if (onMethodEndParameters.Length < 2) { throw new ArgumentException($"The method: {EndMethodName} with {onMethodEndParameters.Length} parameters in type: {integrationType.FullName} has less parameters than required."); } else if (onMethodEndParameters.Length > 3) { throw new ArgumentException($"The method: {EndMethodName} with {onMethodEndParameters.Length} parameters in type: {integrationType.FullName} has more parameters than required."); } if (onMethodEndParameters[onMethodEndParameters.Length - 2].ParameterType != typeof(Exception)) { throw new ArgumentException($"The Exception type parameter of the method: {EndMethodName} in type: {integrationType.FullName} is missing."); } if (onMethodEndParameters[onMethodEndParameters.Length - 1].ParameterType != typeof(CallTargetState)) { throw new ArgumentException($"The CallTargetState type parameter of the method: {EndMethodName} in type: {integrationType.FullName} is missing."); } var callGenericTypes = new List <Type>(); var mustLoadInstance = onMethodEndParameters.Length == 3; var instanceGenericType = genericArgumentsTypes[0]; var instanceGenericConstraint = instanceGenericType.GetGenericParameterConstraints().FirstOrDefault(); Type instanceProxyType = null; if (instanceGenericConstraint != null) { var result = DuckType.GetOrCreateProxyType(instanceGenericConstraint, targetType); instanceProxyType = result.ProxyType; callGenericTypes.Add(instanceProxyType); } else { callGenericTypes.Add(targetType); } var callMethod = new DynamicMethod( $"{onMethodEndMethodInfo.DeclaringType.Name}.{onMethodEndMethodInfo.Name}", typeof(CallTargetReturn), new Type[] { targetType, typeof(Exception), typeof(CallTargetState) }, onMethodEndMethodInfo.Module, true); var ilWriter = callMethod.GetILGenerator(); // Load the instance if is needed if (mustLoadInstance) { ilWriter.Emit(OpCodes.Ldarg_0); if (instanceGenericConstraint != null) { WriteCreateNewProxyInstance(ilWriter, instanceProxyType, targetType); } } // Load the exception ilWriter.Emit(OpCodes.Ldarg_1); // Load the state ilWriter.Emit(OpCodes.Ldarg_2); // Call Method onMethodEndMethodInfo = onMethodEndMethodInfo.MakeGenericMethod(callGenericTypes.ToArray()); ilWriter.EmitCall(OpCodes.Call, onMethodEndMethodInfo, null); ilWriter.Emit(OpCodes.Ret); Logger.Debug($"Created EndMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}]"); return(callMethod); }
internal static DynamicMethod CreateBeginMethodDelegate(Type integrationType, Type targetType, Type[] argumentsTypes) { /* * OnMethodBegin signatures with 1 or more parameters with 1 or more generics: * - CallTargetState OnMethodBegin<TTarget>(TTarget instance); * - CallTargetState OnMethodBegin<TTarget, TArg1>(TTarget instance, TArg1 arg1); * - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2>(TTarget instance, TArg1 arg1, TArg2); * - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2, ...>(TTarget instance, TArg1 arg1, TArg2, ...); * - CallTargetState OnMethodBegin<TTarget>(); * - CallTargetState OnMethodBegin<TTarget, TArg1>(TArg1 arg1); * - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2>(TArg1 arg1, TArg2); * - CallTargetState OnMethodBegin<TTarget, TArg1, TArg2, ...>(TArg1 arg1, TArg2, ...); * */ Logger.Debug($"Creating BeginMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}]"); var onMethodBeginMethodInfo = integrationType.GetMethod(BeginMethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); if (onMethodBeginMethodInfo is null) { Logger.Debug($"'{BeginMethodName}' method was not found in integration type: '{integrationType.FullName}'."); return(null); } if (onMethodBeginMethodInfo.ReturnType != typeof(CallTargetState)) { throw new ArgumentException($"The return type of the method: {BeginMethodName} in type: {integrationType.FullName} is not {nameof(CallTargetState)}"); } var genericArgumentsTypes = onMethodBeginMethodInfo.GetGenericArguments(); if (genericArgumentsTypes.Length < 1) { throw new ArgumentException($"The method: {BeginMethodName} in type: {integrationType.FullName} doesn't have the generic type for the instance type."); } var onMethodBeginParameters = onMethodBeginMethodInfo.GetParameters(); if (onMethodBeginParameters.Length < argumentsTypes.Length) { throw new ArgumentException($"The method: {BeginMethodName} with {onMethodBeginParameters.Length} parameters in type: {integrationType.FullName} has less parameters than required."); } else if (onMethodBeginParameters.Length > argumentsTypes.Length + 1) { throw new ArgumentException($"The method: {BeginMethodName} with {onMethodBeginParameters.Length} parameters in type: {integrationType.FullName} has more parameters than required."); } else if (onMethodBeginParameters.Length != argumentsTypes.Length && onMethodBeginParameters[0].ParameterType != genericArgumentsTypes[0]) { throw new ArgumentException($"The first generic argument for method: {BeginMethodName} in type: {integrationType.FullName} must be the same as the first parameter for the instance value."); } var callGenericTypes = new List <Type>(); var mustLoadInstance = onMethodBeginParameters.Length != argumentsTypes.Length; var instanceGenericType = genericArgumentsTypes[0]; var instanceGenericConstraint = instanceGenericType.GetGenericParameterConstraints().FirstOrDefault(); Type instanceProxyType = null; if (instanceGenericConstraint != null) { var result = DuckType.GetOrCreateProxyType(instanceGenericConstraint, targetType); instanceProxyType = result.ProxyType; callGenericTypes.Add(instanceProxyType); } else { callGenericTypes.Add(targetType); } var callMethod = new DynamicMethod( $"{onMethodBeginMethodInfo.DeclaringType.Name}.{onMethodBeginMethodInfo.Name}", typeof(CallTargetState), new Type[] { targetType }.Concat(argumentsTypes).ToArray(), onMethodBeginMethodInfo.Module, true); var ilWriter = callMethod.GetILGenerator(); // Load the instance if is needed if (mustLoadInstance) { ilWriter.Emit(OpCodes.Ldarg_0); if (instanceGenericConstraint != null) { WriteCreateNewProxyInstance(ilWriter, instanceProxyType, targetType); } } // Load arguments for (var i = mustLoadInstance ? 1 : 0; i < onMethodBeginParameters.Length; i++) { var sourceParameterType = argumentsTypes[mustLoadInstance ? i - 1 : i]; var targetParameterType = onMethodBeginParameters[i].ParameterType; Type targetParameterTypeConstraint = null; Type parameterProxyType = null; if (targetParameterType.IsGenericParameter) { targetParameterType = genericArgumentsTypes[targetParameterType.GenericParameterPosition]; targetParameterTypeConstraint = targetParameterType.GetGenericParameterConstraints().FirstOrDefault(pType => pType != typeof(IDuckType)); if (targetParameterTypeConstraint is null) { callGenericTypes.Add(sourceParameterType); } else { var result = DuckType.GetOrCreateProxyType(targetParameterTypeConstraint, sourceParameterType); parameterProxyType = result.ProxyType; callGenericTypes.Add(parameterProxyType); } } else if (!targetParameterType.IsAssignableFrom(sourceParameterType) && (!(sourceParameterType.IsEnum && targetParameterType.IsEnum))) { throw new InvalidCastException($"The target parameter {targetParameterType} can't be assigned from {sourceParameterType}"); } WriteLoadArgument(ilWriter, i, mustLoadInstance); if (parameterProxyType != null) { WriteCreateNewProxyInstance(ilWriter, parameterProxyType, sourceParameterType); } } // Call method onMethodBeginMethodInfo = onMethodBeginMethodInfo.MakeGenericMethod(callGenericTypes.ToArray()); ilWriter.EmitCall(OpCodes.Call, onMethodBeginMethodInfo, null); ilWriter.Emit(OpCodes.Ret); Logger.Debug($"Created BeginMethod Dynamic Method for '{integrationType.FullName}' integration. [Target={targetType.FullName}]"); return(callMethod); }