Passing Parameters in reflections Windows store Apps - c#

I want to pass some parameters to function that is being called using reflection in a universal windows App. Below is the code which I tried and I am getting an exception "Parameters Count mismatch.". please advice me.
public class myClass
{
public async void btn_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Type type = Type.GetType("moto_Windows.Actions.NextViewAction");
object[] mParam = new object[] { 5, 10 };
var nva = Activator.CreateInstance(type);
await (dynamic)type.GetTypeInfo().GetDeclaredMethod("NextView").Invoke(nva, mParam);
}
}
The class I am trying to invoke look like below
namespace moto_Windows.Actions
{
public class NextViewAction
{
public NextViewAction(object [] obj)
{
//Constructor
}
public async void NextView()
{
//Method to be invoked.
}
}
}

Finally I solved this by passing values in a dictionary through a contructor, my code is
Type type = Type.GetType("moto.Actions." + ctrl.Action.name);
ctrl = (Carrot_Control)btn.DataContext;
Dictionary<string, object> _dict = new Dictionary<string, object>();
dict.Add("a", 5);
_dict.Add("b", 10);
var t = Activator.CreateInstance(type, _dict);
await (dynamic)type.GetTypeInfo().GetDeclaredMethod("NextView").Invoke(t, null);
and the class i tried to invoke
namespace moto_Windows.Actions
{
public class NextViewAction
{
public NextViewAction(Dictionary<string,object> _dict)
{
//Constructor
string a = _dict[a];
string b = _dict[b];
}
public async void NextView()
{
//Method to be invoked.
}
}
}
please post if anybody has better answer.

Related

How to determine the original name of a function passed as a delegate

I want to make a scheduler that runs every 5 minutes, and keeps track of functions that need only be executed once a day. I want to store the last runtime of each job in a (static) dictionary 'LastRuntimePerJob'.
I have created a delegate and a function that only executes the job when it has not been run today.
The code below does not work since nameof(jobToPerform) returns jobToPerform.
How can I get the actual name of the function (Job1) from the delegate jobToPerform?
using System;
using System.Collections.Generic;
namespace Euler.Business.Problem.Progress
{
public class Scheduler
{
public delegate void JobToPerform();
public void Job1()
{
// Perform some task
}
public static Dictionary<string, DateTime> LastRuntimePerJob { get; set; } = new Dictionary<string, DateTime>();
public void RunScheduler()
{
ExecuteWhenNecessary(Job1);
}
public void ExecuteWhenNecessary(JobToPerform jobToPerform)
{
var nameOfCurrentJob = nameof(jobToPerform);
if (!LastRuntimePerJob.ContainsKey(nameOfCurrentJob)
|| LastRuntimePerJob[nameOfCurrentJob] < DateTime.Today)
{
jobToPerform();
if (LastRuntimePerJob.ContainsKey(nameOfCurrentJob))
{
LastRuntimePerJob[nameOfCurrentJob] = DateTime.Now;
}
else
{
LastRuntimePerJob.Add(nameOfCurrentJob, DateTime.Now);
}
}
}
}
}
nameof is used to get the literal name of variables, type or member and it is executed at compile time (no effect at runtime).
I think that you should use jobToPerform.Method.Name to retreive the delegate real method name, so check and try the following code and let me know!
using System;
using System.Collections.Generic;
namespace Euler.Business.Problem.Progress
{
public class Scheduler
{
public delegate void JobToPerform();
public void Job1()
{
// Perform some task
}
public static Dictionary<string, DateTime> LastRuntimePerJob { get; set; } = new Dictionary<string, DateTime>();
public void RunScheduler()
{
ExecuteWhenNecessary(Job1);
}
public void ExecuteWhenNecessary(JobToPerform jobToPerform)
{
//var nameOfCurrentJob = nameof(jobToPerform);
var nameOfCurrentJob = jobToPerform.Method.Name; //Returns delegate method name
if (!LastRuntimePerJob.ContainsKey(nameOfCurrentJob)
|| LastRuntimePerJob[nameOfCurrentJob] < DateTime.Today)
{
jobToPerform();
if (LastRuntimePerJob.ContainsKey(nameOfCurrentJob))
{
LastRuntimePerJob[nameOfCurrentJob] = DateTime.Now;
}
else
{
LastRuntimePerJob.Add(nameOfCurrentJob, DateTime.Now);
}
}
}
}
}
EDIT - Note: if the delegate is anonymous you retreive the runtime assigned name:
public void RunScheduler()
{
ExecuteWhenNecessary(() => { Console.WriteLine("Hello"); });
}
the method name will be like: <RunScheduler>b__6_0.
You can modify the ExecuteWhenNecessary method signature to specify the method name you want to use as Dictionary Key:
public void ExecuteWhenNecessary(JobToPerform jobToPerform, , string nameOfCurrentJob = null)
{
if (string.IsNullOrWhiteSpace(nameOfCurrentJob))
{
nameOfCurrentJob = jobToPerform.Method.Name;
}
if (!LastRuntimePerJob.ContainsKey(nameOfCurrentJob)
|| LastRuntimePerJob[nameOfCurrentJob] < DateTime.Today)
{
jobToPerform();
if (LastRuntimePerJob.ContainsKey(nameOfCurrentJob))
{
LastRuntimePerJob[nameOfCurrentJob] = DateTime.Now;
}
else
{
LastRuntimePerJob.Add(nameOfCurrentJob, DateTime.Now);
}
}
}
And call method like:
ExecuteWhenNecessary(() => { Console.WriteLine("Hello"); }, "MyMethodName"); //Anonymous
ExecuteWhenNecessary(() => { Console.WriteLine("Hello"); }, nameof(Job1));

C# Pass any method as parameter

I'm making a networking application where I want to implement strongly typed RPC. As result I'd like to be able to pass methods no matter the parameters so I can get them and store them in a dictionary so I can construct request parameters properly as well once a packet arrive I am able to read it using the parameters the same remote method used
I'd like something like this:
Register(Enum key, [method with unknown parameters])
In C# 8.0 using generics and Delegate Constraint you can do something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
public class Program
{
public static void Main(params string[] args)
{
var app = new NetworkingApplication();
app.Register<Action<int, string>>(PacketType.Type1, Method1, 1, "string1 argument");
app.Register<Func<string, string>>(PacketType.Type2, Method2, "string2 argument");
app.OnPacketReceived(PacketType.Type1);
app.OnPacketReceived(PacketType.Type2);
}
public static void Method1(int arg1, string arg2)
{
Console.WriteLine($"Method1 Invoked with args: {arg1}, {arg2}");
}
public static string Method2(string arg1)
{
Console.WriteLine($"Method2 Invoked with args: {arg1}");
return "Foo";
}
}
public class NetworkingApplication
{
private readonly IDictionary<PacketType, DelegateInvoker> _registrations;
public NetworkingApplication()
{
_registrations = new Dictionary<PacketType, DelegateInvoker>();
}
public void Register<TDelegate>(PacketType packetType, TDelegate #delegate, params object[] args)
where TDelegate : Delegate
{
_registrations[packetType] = new DelegateInvoker(#delegate, args);
}
//invoke this when the packet is received
public void OnPacketReceived(PacketType type)
{
if (_registrations.TryGetValue(type, out var invoker))
{
invoker.Invoke();
}
}
private class DelegateInvoker
{
public DelegateInvoker(Delegate #delegate, object[] args)
{
Delegate = #delegate;
Arguments = args;
}
private Delegate Delegate { get; }
private object[] Arguments { get; }
public void Invoke()
{
Delegate.Method.Invoke(Delegate.Target, Arguments);
}
}
}
public enum PacketType
{
Type1,
Type2,
Type3
}
}
As mentioned above you can use MethodInfo, it belongs to the System.Reflection namespace. To do this, first get the Type type of the object like this:
var type = obj.GetType()
After this you can use var methods = type.GetMethods(). This will give you an MethodInfo[]. Search the element, using your favorite method for doing so. Such as Linq:
var method = methods.Where(it => it.Name == __yourName__).LastOrDefault();
*where yourName is the name of your method.
Now you have the method you are looking for. Get the parameters using
var parameters = method.getParameters();
And there are the parameters as ParameterInfo[].
From there you can get the type of each parameter using the parameter.ParameterType property.
This being said be very careful with Reflection, it is very, very powerful but can decrease performance heavily, when overused.
Have look at it System.Reflection namespace here .
You can now add the method to a collection, such as a dictionary:
var dictionary = new Dictionary<int,MethodInfo>();
dictionary.Add(1, method);
And retrieve it like this:
var method = dictionary[1];
To call the function you can user method.Invoke() and pass in the parameters as need.
EDIT:
If you would like to send the parameters as well as the function over a network. You could create a new class that serves as a DTO Data Transfer Object. This class could have as property an Array of parameters (ParameterInfo[]), the MethodInfo and anything else you want.
You could then serialize the object (maybe json) and send it to another system, that could then deserialize it, and Invoke the MethodInfo obj
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp
{
public class Program
{
public static void Main(params string[] args)
{
var app = new NetworkingApplication();
app.Register(PacketType.Type1, () =>
{
Console.WriteLine("Type1 Packet is received!");
});
}
}
public class NetworkingApplication
{
private readonly IDictionary<PacketType, Action> _registrations;
public NetworkingApplication()
{
_registrations = new Dictionary<PacketType, Action>();
}
public void Register(PacketType packetType, Action method)
{
_registrations[packetType] = method;
}
//invoke this when the packet is received
public void OnPacketReceived(PacketType type)
{
if (_registrations.TryGetValue(type, out var action))
{
action?.Invoke();
}
}
}
public enum PacketType
{
Type1,Type2,Type3
}
}

Create wrapper around interface and get method/paramters called

Lets say I have this interface
public interface ITest
{
int Property1 { get; set; }
void Method1();
string GetMethod1();
void MethodWithParam(string str);
}
How can I create a wrapper object around this?
And then capture the methods called or paramters and values accessed etc.
For example:
var myWrapper = GetWrapper<ITest>();
myWrapper.Property1 = 7;
How would I be able to using reflection or whatever to know the following:
Paramter name being called and value being set
var data = myWrapper.GetMethod1("Test");
Get method name of "GetMethod1" along with paramaters and then return a value based on that?
Hope makes sense
Ok so answer quite simple using Castle Core proxy generator:
https://github.com/castleproject/Core
public interface ITest
{
int Property1 { get; set; }
void Method1();
string GetMethod1();
void MethodWithParam(string str);
}
public static class Wrapper
{
private class MethodInterceptor : IInterceptor
{
Action<IInvocation> OnIntercept;
public MethodInterceptor(Action<IInvocation> OnIntercept)
{
this.OnIntercept = OnIntercept;
}
public void Intercept(IInvocation invocation)
{
OnIntercept?.Invoke(invocation);
}
}
private static void CallAPI(IInvocation invocation)
{
var methodName = invocation.Method.Name;
var valuespassed = invocation.Arguments;
var retType = invocation.Method.ReturnType.FullName;
//DO API THINGS NOW
}
public static T Get<T>()
{
ProxyGenerator generator = new ProxyGenerator();
var interceptor = new MethodInterceptor(CallAPI);
var c = generator.CreateInterfaceProxyWithoutTarget<ITest>(interceptor);
return (T)c;
}
}
public class Test123
{
public void Test()
{
var c = Wrapper.Get<ITest>();
c.Property1 = 7;
var propval = c.Property1;
}
}
Any action on c calls the intercept function where can get everything from method name being called to arguments passed.

Creating a read only generic List from a derived class

I'm developing a library for developers where they have to create a class that inherits from a class I created.
This base class essentially manages an array of objects for the developer, however the developer gets to specify the type of these objects they want the base class to manage.
So the developer essentially just tells the base class to create an array, then only has read only access to that array. The base class will (depending on the state of the application) add or remove objects from the array.
I'm stuck at finding the right data type to store such a thing. I've tried ref and out but that got me nowhere. The closest I got was with a Dictionary but that idea fell apart because C# is actually just copying the value into the dictionary instead of referencing or pointing to it.
Here is a quick example I threw together:
public static void Main()
{
Derived d = new Derived();
d.InitBase();
d.Init();
d.CheckArray();
d.AddElement<GenericObject>(new GenericObject{ i = 2 });
d.CheckArray();
}
public class Base {
Dictionary<Type, List<object>> ArrayReferences;
public void InitBase() {
ArrayReferences = new Dictionary<Type, List<object>>();
}
protected ReadOnlyCollection<T> RegisterArray<T>() {
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
}
public void AddElement<T>(T obj) {
ArrayReferences[typeof(T)].Add(obj);
}
public void RemoveElement<T>(T obj) {
ArrayReferences[typeof(T)].Remove(obj);
}
}
public class Derived: Base {
ReadOnlyCollection<GenericObject> arr;
public void Init() {
arr = RegisterArray<GenericObject>();
}
public void CheckArray() {
Console.WriteLine(arr.Count());
}
}
public class GenericObject {
public int i = 0;
}
Output:
0
0
Dictionary obviously doesn't store the values as references like I want it to. So what other technique does C# have or is this simply not possible? Also not sure how many issues unsafe will cause me so I'm scared going that route.
While I think there are better ways of handling this issue, this can be done.
Instead of storing a List<object> reference, which isn't compatible with a List<T>, store an object. Use a static in Base to hold the Dictionary so there is one Dictionary for all derived classes.
public static void Main() {
var d = new Derived();
d.CheckCollection("d before AddElement");
d.AddElement(new GenericObject { i = 2 });
d.CheckCollection("d after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
var d2 = new Derived2();
d2.CheckCollection("d2 before AddElement");
d2.AddElement(new GenericObject2 { i = 4 });
d2.AddElement(new GenericObject2 { i = 5 });
d2.CheckCollection("d2 after AddElement");
Console.WriteLine($"ListCount = {Base.ListCount}");
}
public class Base {
static Dictionary<Type, object> ListReferences = new Dictionary<Type, object>();
public static int ListCount => ListReferences.Count();
protected ReadOnlyCollection<T> RegisterList<T>() {
var managedList = new List<T>();
ListReferences.Add(typeof(T), managedList);
return managedList.AsReadOnly();
}
public void AddElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Add(obj);
}
public void RemoveElement<T>(T obj) {
((List<T>)ListReferences[typeof(T)]).Remove(obj);
}
}
public class Derived : Base {
ReadOnlyCollection<GenericObject> roc;
public Derived() {
roc = RegisterList<GenericObject>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class Derived2 : Base {
ReadOnlyCollection<GenericObject2> roc;
public Derived2() {
roc = RegisterList<GenericObject2>();
}
public void CheckCollection(string msg) {
Console.WriteLine(msg);
Console.WriteLine(roc.Count());
}
}
public class GenericObject {
public int i = 0;
}
public class GenericObject2 {
public int i = 0;
}
PS Also, don't name methods and variables with "array" when you are using Lists.
The following code you've written makes a copy of your list at the time you created it - so it is always empty, no matter what you add to the list afterwards.
List<object> managedArray = new List<object>();
ArrayReferences.Add(typeof(T), managedArray);
return Array.AsReadOnly(managedArray.Select(s => (T)s).ToArray());
Here is how you should write your code to get what you want:
public static void Main()
{
Derived d = new Derived();
Console.WriteLine(d.AsReadOnly().Count);
d.AddElement(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class Base<T>
{
List<T> _items = new List<T>();
public ReadOnlyCollection<T> AsReadOnly()
{
return Array.AsReadOnly(_items.ToArray());
}
public void AddElement(T obj)
{
_items.Add(obj);
}
public void RemoveElement(T obj)
{
_items.Remove(obj);
}
}
public class Derived : Base<GenericObject>
{
}
public class GenericObject
{
public int i = 0;
}
That outputs:
0
1
Now, it's worth considering that List<T> already has a AsReadOnly() method, so you could simply write this:
public static void Main()
{
var d = new List<GenericObject>();
Console.WriteLine(d.AsReadOnly().Count);
d.Add(new GenericObject { i = 2 });
Console.WriteLine(d.AsReadOnly().Count);
}
public class GenericObject
{
public int i = 0;
}
That works too.
Here's how you should do this to hold more than one list at a time. There's no need for inheritance.
public static void Main()
{
Repository r = new Repository();
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
r.AddElement<GenericObject>(new GenericObject { i = 2 });
Console.WriteLine(r.AsReadOnly<GenericObject>().Count);
}
public class Repository
{
private Dictionary<Type, object> _references = new Dictionary<Type, object>();
private void Ensure<T>()
{
if (!_references.ContainsKey(typeof(T)))
{
_references[typeof(T)] = new List<T>();
}
}
public ReadOnlyCollection<T> AsReadOnly<T>()
{
this.Ensure<T>();
return (_references[typeof(T)] as List<T>).AsReadOnly();
}
public void AddElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Add(obj);
}
public void RemoveElement<T>(T obj)
{
this.Ensure<T>();
(_references[typeof(T)] as List<T>).Remove(obj);
}
}
public class GenericObject
{
public int i = 0;
}
In your base (or encapsulated class if you choose to go that way):
protected ReadOnlyCollection<T> GetSnapshot<T>() {
return Array.AsReadOnly(ArrayReferences[typeof(T)].Select(s => (T)s).ToArray());
}
Then you'd also add any other methods to view the data, e.g. to get a count:
protected int GetCount<T>() {
return ArrayReferences[typeof(T)].Count;
}

How can i get the parameter values of an anonymous method passed as a func?

I am calling methods on a remote system. The remote system implements an interface that both systems have a copy of (via shared nuget repository). At the moment i am sending the requests like this:
var oldRequest = new FooRequest("GetEmployeeById", new object[] { "myPartner", 42, DateTime.Now.AddDays(-1) });
Here is the interface:
public class FooResponse<T> { }
public interface IFooController
{
FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}
As you can image, sometimes programmers passes arguments in the wrong order to the array in the constructor, and things start to fail. To resolve this I have created the following code to have intellisense support when creating the FooRequest:
public static FooRequest Create<T>(Func<FooResponse<T>> func)
{
return new FooRequest(null, null); // Here goes some magic reflection stuff instead of null.
}
It is now possible to create a FooRequest like this:
public static IFooController iFooController => (IFooController)new object();
public static FooRequest CreateRequest<T>(Func<FooResponse<T>> func)
{
return FooRequest.Create(func);
}
var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
My question then is: How will i be able to get the name of the method and the value of the parameters in the FooRequest.Create-method?
I have exhausted both my reflection and google-skills trying to find the values, but no luck so far.
Complete compiling code can be found here if someone wants to give it a shot: http://ideone.com/ovWseI
Here is a sketch of how you can do this with expressions:
public class Test {
public static IFooController iFooController => (IFooController) new object();
public static FooRequest CreateRequest<T>(Expression<Func<FooResponse<T>>> func) {
return FooRequest.Create(func);
}
public static void Main() {
var newRequest = CreateRequest(() => iFooController.GetEmployeeById("myPartner", 42, DateTime.Now.AddDays(-1)));
Console.ReadKey();
}
}
public class FooRequest {
public static FooRequest Create<T>(Expression<Func<FooResponse<T>>> func) {
var call = (MethodCallExpression) func.Body;
var arguments = new List<object>();
foreach (var arg in call.Arguments) {
var constant = arg as ConstantExpression;
if (constant != null) {
arguments.Add(constant.Value);
}
else {
var evaled = Expression.Lambda(arg).Compile().DynamicInvoke();
arguments.Add(evaled);
}
}
return new FooRequest(call.Method.Name, arguments.ToArray());
}
public FooRequest(string function, object[] data = null) {
//SendRequestToServiceBus(function, data);
Console.Write($"Function name: {function}");
}
}
public class FooResponse<T> {
}
public interface IFooController {
FooResponse<string> GetEmployeeById(string partnerName, int employeeId, DateTime? ifModifiedSince);
}

Categories