/// <summary> /// Contributes to the specified plan. /// </summary> /// <param name="plan">The plan that is being generated.</param> public void Execute(IPlan plan) { EventInfo[] events = plan.Type.GetEvents(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (EventInfo evt in events) { IEnumerable <PublishAttribute> attributes = evt.GetAttributes <PublishAttribute>(); foreach (PublishAttribute attribute in attributes) { plan.Add(new PublicationDirective(attribute.Channel, evt)); } } MethodInfo[] methods = plan.Type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (MethodInfo method in methods) { IEnumerable <SubscribeAttribute> attributes = method.GetAttributes <SubscribeAttribute>(); foreach (SubscribeAttribute attribute in attributes) { MethodInjector injector = InjectorFactory.Create(method); plan.Add(new SubscriptionDirective(attribute.Channel, injector, attribute.Thread)); } } }
public void SetupTest() { var mi = new MethodInjector<CustomerWithComparer>(); // データ。 var customers = new CustomerWithComparer[] { mi.Setup(new CustomerWithComparer() { CustomerKey = 1, FirstName = "Mitsuru", LastName = "Nishi", ContractDate = new DateTime(2010, 12, 3) }), mi.Setup(new CustomerWithComparer() { CustomerKey = 1, FirstName = "Mitsuru", LastName = "Nishi", ContractDate = new DateTime(2010, 12, 3) }), mi.Setup(new CustomerWithComparer() { CustomerKey = 2, FirstName = "Izumiya", LastName = "Masako", ContractDate = new DateTime(2010, 10, 23) }), mi.Setup(new CustomerWithComparer() { CustomerKey = 1, FirstName = "Mitsuru", LastName = "Akatani", ContractDate = new DateTime(2010, 12, 3) }) }; // プロパティを使って比較が行われる。 Assert.IsFalse(object.ReferenceEquals(customers[0], customers[1])); Assert.IsTrue(customers[0].Equals(customers[1])); Assert.IsTrue(customers[0].GetHashCode() == customers[1].GetHashCode()); Assert.IsFalse(object.ReferenceEquals(customers[0], customers[2])); Assert.IsFalse(customers[0].Equals(customers[2])); Assert.IsFalse(customers[0].GetHashCode() == customers[2].GetHashCode()); // LastName は比較対象にしていない。 Assert.IsFalse(object.ReferenceEquals(customers[0], customers[3])); Assert.IsTrue(customers[0].Equals(customers[3])); Assert.IsTrue(customers[0].GetHashCode() == customers[3].GetHashCode()); }
/// <summary> /// Initializes a new instance of the <see cref="SubscriptionDirective"/> class. /// </summary> /// <param name="channel">The name of the channel that is to be susbcribed to.</param> /// <param name="injector">The injector that triggers the method.</param> /// <param name="thread">The thread on which the message should be delivered.</param> public SubscriptionDirective(string channel, MethodInjector injector, DeliveryThread thread) { Ensure.ArgumentNotNullOrEmpty(channel, "channel"); Ensure.ArgumentNotNull(injector, "injector"); _channel = channel; _injector = injector; _thread = thread; }
/// <summary> /// Initializes a new instance of the <see cref="SubscriptionDirective"/> class. /// </summary> /// <param name="channel">The name of the channel that is to be susbcribed to.</param> /// <param name="injector">The injector that triggers the method.</param> /// <param name="thread">The thread on which the message should be delivered.</param> public SubscriptionDirective( string channel, MethodInjector injector, DeliveryThread thread ) { Ensure.ArgumentNotNullOrEmpty( channel, "channel" ); Ensure.ArgumentNotNull( injector, "injector" ); _channel = channel; _injector = injector; _thread = thread; }
public WhenMethodInjectorIsInvokedOnNonVoidMethod() { #if !WINRT method = typeof(Samurai).GetMethod("Attack"); #else method = typeof(Samurai).GetTypeInfo().GetDeclaredMethod("Attack"); #endif injector = injectorFactory.Create(method); }
public bool PatchMethod2(MethodDefinition method, Injection injection) { bool success = true; if (method.IsConstructor || method.IsAbstract || method.IsSetter || (method.IsSpecialName && !method.IsGetter) || // to allow getter methods method.IsGenericInstance || method.IsManaged == false || method.Body == null) { SendMessage("Ignored method: " + method.Name, MessageType.Warning); return(true); } try { var constructor = injection.Constructor; constructor.Resolve(); bool isInjected = method.Body.Variables.Count(x => x.VariableType.Scope == injection.TypeReference.Scope && x.VariableType.FullName == injection.TypeReference.FullName && x.VariableType.Namespace == injection.TypeReference.Namespace) > 0; MethodInjector editor = new MethodInjector(method); VariableDefinition vInject = editor.AddVariable(injection.TypeReference); VariableDefinition vInjection = editor.AddVariable(_cinjection); VariableDefinition vObjectArray = editor.AddVariable(Assembly.ImportType <object[]>()); Instruction firstExistingInstruction = method.Body.Instructions[0]; // create constructor of Injector editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newobj, constructor)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vInject)); #region OnInvoke without Param editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInject)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, injection.OnInvoke)); #endregion method.Resolve(); SendMessage("Injected method " + method, MessageType.Output); } catch (Exception ex) { SendMessage(ex.Message, MessageType.Error); return(false); } return(true); }
public MethodFinder(MethodGenerifier methodGenerifier, MethodInjector methodInjector, TypeNodeBuilder typeNodeBuilder, ModuleReader moduleReader, Logger logger, TypeResolver typeResolver, EventInvokerNameResolver eventInvokerNameResolver) { this.methodGenerifier = methodGenerifier; this.methodInjector = methodInjector; this.typeNodeBuilder = typeNodeBuilder; this.moduleReader = moduleReader; this.logger = logger; this.typeResolver = typeResolver; this.eventInvokerNameResolver = eventInvokerNameResolver; }
public virtual void Engage() { // Iterate the selected methods var selector = new MethodSelector(); foreach (var method in selector.Select(context)) { var methodInjector = new MethodInjector(context, method, ResolveArguments(method)); methodInjector.Inject(); } }
/// <summary> /// Releases all resources held by the object. /// </summary> /// <param name="disposing"><see langword="True"/> if managed objects should be disposed, otherwise <see langword="false"/>.</param> public override void Dispose( bool disposing ) { if ( disposing && !IsDisposed ) { _channel = null; _subscriber = null; _injector = null; } base.Dispose( disposing ); }
/// <summary> /// Adds a subscription to the channel. /// </summary> /// <param name="subscriber">The object that will subscribe to events.</param> /// <param name="injector">The injector that will be triggered when an event occurs.</param> /// <param name="thread">The thread on which the message should be delivered.</param> public void AddSubscription(object subscriber, MethodInjector injector, DeliveryThread thread) { Ensure.NotDisposed(this); var factory = Kernel.Components.Get <IMessageSubscriptionFactory>(); lock ( _subscriptions ) { _subscriptions.Add(factory.Create(this, subscriber, injector, thread)); } }
/// <summary> /// Releases all resources held by the object. /// </summary> /// <param name="disposing"><see langword="True"/> if managed objects should be disposed, otherwise <see langword="false"/>.</param> public override void Dispose(bool disposing) { if (disposing && !IsDisposed) { _channel = null; _subscriber = null; _injector = null; } base.Dispose(disposing); }
public static string GetInjectedAssembly(string assemblyToTest) { var methodInjectorTask = new MethodInjector(new TestLogger()); methodInjectorTask.References = "/Users/pranshuaggarwal/.nuget/packages/xamarin.forms/3.2.0.839982/lib/netstandard2.0/Xamarin.Forms.Core.dll;/Users/pranshuaggarwal/.nuget/packages/prism.forms/7.1.0.431/lib/netstandard2.0/Prism.Forms.dll;/Users/pranshuaggarwal/.nuget/packages/prism.core/7.1.0.431/lib/netstandard2.0/Prism.dll"; var assemblyPath = Path.Combine(assemblyLocation, $"{assemblyToTest}.dll"); var tempAssemblyPath = Path.Combine(Path.GetDirectoryName(assemblyPath), $"{Path.GetFileNameWithoutExtension(assemblyPath)}.temp.{Path.GetExtension(assemblyPath)}"); methodInjectorTask.InjectCode(assemblyPath, tempAssemblyPath); return(tempAssemblyPath); }
/// <summary> /// Initializes a new instance of the <see cref="StandardMessageSubscription"/> class. /// </summary> /// <param name="channel">The channel associated with the subscription.</param> /// <param name="subscriber">The object that will receive the channel events.</param> /// <param name="injector">The injector that will be triggered an event occurs.</param> /// <param name="deliveryThread">The thread context that should be used to deliver the message.</param> public StandardMessageSubscription(IMessageChannel channel, object subscriber, MethodInjector injector, DeliveryThread deliveryThread) { _channel = channel; _subscriber = subscriber; _injector = injector; _deliveryThread = deliveryThread; #if !SILVERLIGHT && !NETCF if (deliveryThread == DeliveryThread.UserInterface) { _syncContext = SynchronizationContext.Current; } #endif }
public void CreatesTargetsForMethodParameters() { var method = typeof(Dummy).GetMethod("MethodA"); MethodInjector injector = delegate { }; directive = new FakeMethodInjectionDirective(method, injector); ITarget[] targets = directive.Targets; targets.Length.Should().Be(3); targets[0].Name.Should().Be("foo"); targets[0].Type.Should().Be(typeof(int)); targets[1].Name.Should().Be("bar"); targets[1].Type.Should().Be(typeof(string)); targets[2].Name.Should().Be("baz"); targets[2].Type.Should().Be(typeof(IWeapon)); }
public WhenActivateIsCalled() { reference = new InstanceReference { Instance = instance }; contextMock = new Mock<IContext>(); planMock = new Mock<IPlan>(); injector1 = (x, args) => { injector1WasCalled = true; }; injector2 = (x, args) => { injector2WasCalled = true; }; directives = new[] { new FakeMethodInjectionDirective(method1, injector1), new FakeMethodInjectionDirective(method2, injector2) }; contextMock.SetupGet(x => x.Plan).Returns(planMock.Object); planMock.Setup(x => x.GetAll<MethodInjectionDirective>()).Returns(directives); }
/// <summary> /// Removes a subscription from the channel. /// </summary> /// <param name="subscriber">The object that is subscribing to events.</param> /// <param name="injector">The injector associated with the subscription.</param> /// <returns><see langword="true"/> if the subscription was removed, or <see langword="false"/> if no such publication exists.</returns> public bool RemoveSubscription(object subscriber, MethodInjector injector) { Ensure.NotDisposed(this); lock ( _subscriptions ) { foreach (IMessageSubscription subscription in _subscriptions) { if ((subscription.Subscriber == subscriber) && (subscription.Injector.Method == injector.Method)) { _subscriptions.Remove(subscription); return(true); } } } return(false); }
public WhenActivateIsCalled() { reference = new InstanceReference { Instance = instance }; contextMock = new Mock <IContext>(); planMock = new Mock <IPlan>(); injector1 = (x, args) => { injector1WasCalled = true; }; injector2 = (x, args) => { injector2WasCalled = true; }; directives = new[] { new FakeMethodInjectionDirective(method1, injector1), new FakeMethodInjectionDirective(method2, injector2) }; contextMock.SetupGet(x => x.Plan).Returns(planMock.Object); planMock.Setup(x => x.GetAll <MethodInjectionDirective>()).Returns(directives); }
public bool PatchMethod(MethodDefinition method, Injection injection) { bool success = true; if (method.IsConstructor || method.IsAbstract || method.IsSetter || (method.IsSpecialName && !method.IsGetter) || // to allow getter methods method.IsGenericInstance || method.IsManaged == false || method.Body == null) { SendMessage("Ignored method: " + method.Name, MessageType.Warning); return(true); } try { var constructor = injection.Constructor; constructor.Resolve(); bool isInjected = method.Body.Variables.Count(x => x.VariableType.Scope == injection.TypeReference.Scope && x.VariableType.FullName == injection.TypeReference.FullName && x.VariableType.Namespace == injection.TypeReference.Namespace) > 0; if (isInjected) // already injected { SendMessage("Already injected method " + method.Name + " with " + injection.TypeReference.Name, MessageType.Warning); return(true); } MethodInjector editor = new MethodInjector(method); VariableDefinition vInject = editor.AddVariable(injection.TypeReference); VariableDefinition vInjection = editor.AddVariable(_cinjection); VariableDefinition vObjectArray = editor.AddVariable(Assembly.ImportType <object[]>()); Instruction firstExistingInstruction = method.Body.Instructions[0]; // create constructor of Injector editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newobj, constructor)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vInject)); #region OnInvoke without Param //editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInject)); //editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, injection.OnInvoke)); #endregion #region OnInvoke with Param // create constructor of CInjection editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newobj, _cinjectionCtor)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vInjection)); // create parameter of GetCurrentMethod editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Call, _methodGetCurrentMethod)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, _methodSetMethod)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Nop)); // create parameter of GetExecutingAssembly editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Call, _methodGetExecutingAssembly)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, _methodSetExecutingAssembly)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Nop)); if (method.Parameters.Count > 0) { // create array of object (arguments) editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldc_I4, method.Parameters.Count)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Newarr, Assembly.ImportType <object>())); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stloc_S, vObjectArray)); for (int i = 0; i < method.Parameters.Count; i++) { bool processAsNormal = true; if (method.Parameters[i].ParameterType.IsByReference) { /* Sample Instruction set: * L_002a: ldloc.2 * L_002b: ldc.i4.0 * L_002c: ldarg.1 * L_002d: ldind.ref * L_002e: stelem.ref * */ editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vObjectArray)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldc_I4, i)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldarg, method.Parameters[i])); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldind_Ref)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stelem_Ref)); processAsNormal = false; } //else if (method.Parameters[i].ParameterType.IsArray) //{ //} //else if (method.Parameters[i].ParameterType.IsDefinition) // delegate needs no seperate handling //{ //} else if (method.Parameters[i].ParameterType.IsFunctionPointer) { } //else if (method.Parameters[i].ParameterType.IsOptionalModifier) //{ //} else if (method.Parameters[i].ParameterType.IsPointer) { } else { processAsNormal = true; } if (processAsNormal) { /* Sample Instruction set: for simple PARAMETER * L_0036: ldloc.s objArray * L_0038: ldc.i4 0 * L_003d: ldarg array * L_0041: box Int32 <-------------- anything can be here * L_0046: stelem.ref * */ /* Sample Instruction set: for ARRAY * L_0036: ldloc.s objArray * L_0038: ldc.i4 0 * L_003d: ldarg array * L_0041: box string[] * L_0046: stelem.ref * */ editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vObjectArray)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldc_I4, i)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldarg, method.Parameters[i])); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Box, method.Parameters[i].ParameterType)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Stelem_Ref)); } } editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vObjectArray)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, _methodSetArguments)); } // call OnInvoke with appropriate parameters editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInject)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Ldloc_S, vInjection)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Callvirt, injection.OnInvoke)); editor.InsertBefore(firstExistingInstruction, editor.Create(OpCodes.Nop)); #endregion #region OnComplete Instruction[] exitInstructions = method.Body.Instructions.Where(x => x.OpCode == OpCodes.Ret).ToArray(); for (int i = 0; i < exitInstructions.Length; i++) { var previous = exitInstructions[i].Previous; // most likely previous statement will be NOP, LDLOC.0 (pop, or load from stack) editor.InsertBefore(previous, editor.Create(OpCodes.Ldloc_S, vInject)); editor.InsertBefore(previous, editor.Create(OpCodes.Callvirt, injection.OnComplete)); Debug.WriteLine(method.Name + " " + method.ReturnType.Name + " " + previous.OpCode); } #endregion method.Resolve(); SendMessage("Injected method " + method, MessageType.Output); } catch (Exception ex) { SendMessage(ex.Message, MessageType.Error); return(false); } return(true); }
public WhenMethodInjectorIsInvokedOnNonVoidMethod() { method = typeof(Samurai).GetMethod("Attack"); injector = injectorFactory.Create(method); }
/// <summary> /// Creates a subscription for the specified channel. /// </summary> /// <param name="channel">The channel that will be subscribed to.</param> /// <param name="subscriber">The object that will receive events from the channel.</param> /// <param name="injector">The injector that will be called to trigger the event handler.</param> /// <param name="deliveryThread">The thread on which the subscription will be delivered.</param> /// <returns>The newly-created subscription.</returns> public IMessageSubscription Create(IMessageChannel channel, object subscriber, MethodInjector injector, DeliveryThread deliveryThread) { return(new StandardMessageSubscription(channel, subscriber, injector, deliveryThread)); }
public WhenMethodInjectorIsInvokedOnVoidMethod() { method = typeof(Samurai).GetMethod("SetName"); injector = injectorFactory.Create(method); }
public WhenMethodInjectorIsInvokedOnVoidMethod() { this.method = typeof(Samurai).GetMethod("SetName"); this.injector = this.injectorFactory.Create(this.method); }
/// <summary> /// Initializes a new instance of the <see cref="MethodDirective"/> class. /// </summary> /// <param name="method">The method described by the directive.</param> /// <param name="injector">The injector that will be triggered.</param> public MethodDirective(MethodInfo method, MethodInjector injector) : base(method, injector) { }
/// <summary> /// Initializes a new instance of the <see cref="StandardMessageSubscription"/> class. /// </summary> /// <param name="channel">The channel associated with the subscription.</param> /// <param name="subscriber">The object that will receive the channel events.</param> /// <param name="injector">The injector that will be triggered an event occurs.</param> /// <param name="deliveryThread">The thread context that should be used to deliver the message.</param> public StandardMessageSubscription( IMessageChannel channel, object subscriber, MethodInjector injector, DeliveryThread deliveryThread ) { _channel = channel; _subscriber = subscriber; _injector = injector; _deliveryThread = deliveryThread; #if !SILVERLIGHT && !NETCF if ( deliveryThread == DeliveryThread.UserInterface ) { _syncContext = SynchronizationContext.Current; } #endif }
public AssemblyProcessor(MethodInjector loadedCheckerInjector, ImplementsInterfaceFinder implementsInterfaceFinder, Action <string> logInfo) { this.loadedCheckerInjector = loadedCheckerInjector; this.implementsInterfaceFinder = implementsInterfaceFinder; this.logInfo = logInfo; }
public FakeMethodInjectionDirective(MethodInfo method, MethodInjector injector) : base(method, injector) { }
public MethodInjectorTest() { methodInjectorTask = new MethodInjector(new TestLogger()); methodInjectorTask.ProjectDirectory = "/Users/pranshuaggarwal/Xenolt/HotReloading/Build/BuildSample"; methodInjectorTask.AssemblyFile = "obj/Debug/netstandard2.0/BuildSample.dll"; }
/// <summary> /// Removes a subscription from the channel. /// </summary> /// <param name="subscriber">The object that is subscribing to events.</param> /// <param name="injector">The injector associated with the subscription.</param> /// <returns><see langword="true"/> if the subscription was removed, or <see langword="false"/> if no such publication exists.</returns> public bool RemoveSubscription( object subscriber, MethodInjector injector ) { Ensure.NotDisposed( this ); lock ( _subscriptions ) { foreach ( IMessageSubscription subscription in _subscriptions ) { if ( ( subscription.Subscriber == subscriber ) && ( subscription.Injector.Method == injector.Method ) ) { _subscriptions.Remove( subscription ); return true; } } } return false; }
/// <summary> /// Adds a subscription to the channel. /// </summary> /// <param name="subscriber">The object that will subscribe to events.</param> /// <param name="injector">The injector that will be triggered when an event occurs.</param> /// <param name="thread">The thread on which the message should be delivered.</param> public void AddSubscription( object subscriber, MethodInjector injector, DeliveryThread thread ) { Ensure.NotDisposed( this ); var factory = Kernel.Components.Get<IMessageSubscriptionFactory>(); lock ( _subscriptions ) { _subscriptions.Add( factory.Create( this, subscriber, injector, thread ) ); } }
private void FindExitStatements(MethodInjector editor, Injection injection) { //TODO: Find Exit Statements }
/// <summary> /// Creates a subscription for the specified channel. /// </summary> /// <param name="channel">The channel that will be subscribed to.</param> /// <param name="subscriber">The object that will receive events from the channel.</param> /// <param name="injector">The injector that will be called to trigger the event handler.</param> /// <param name="deliveryThread">The thread on which the subscription will be delivered.</param> /// <returns>The newly-created subscription.</returns> public IMessageSubscription Create( IMessageChannel channel, object subscriber, MethodInjector injector, DeliveryThread deliveryThread ) { return new StandardMessageSubscription( channel, subscriber, injector, deliveryThread ); }