C# equivalent of Actionscript's function apply and call? - c#

I'm just curious, in AS3 I can use the methods apply and call, as in:
aFn.apply( thisObj, arrayOfArgs );
or
aFn.call( thisObj, a, b, c );
is there an equivalent syntax in C#?
Preferably without using Reflection.
Thank you for reading.

Not quite. Given a particular instance method like say Object#Equals
You can use Delegate.CreateDelegate to create an "open" delegate. Which will unbind the "this" parameter. Unfortunately, it will not call that particular implementation of Equals, it will call this's class implementation. As Object#Equals is a virtual method.
Once you have your open delegate you can use dynamic invoke. To apply, but the first element in the array is the this.
You can do this::
var #this = new { a = 3, b = 4 };
var other = new { a = 3, b = 4 };
Func<object, object, bool> equalFn = Delegate.CreateDelegate(
typeof(Func<object, object, bool>),
typeof(object).GetMethod("Equals",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance)) as Func<object, object, bool>;
equalFn.Invoke(#this, other); // call example
equalFn.DynamicInvoke(new[] { #this, other }); // apply example
Open delegates are fairly useful. I can't really recommend a good use for DynamicInvoke if you know your types though.

Related

C# syntax, assign delegate to a class, and call later

I have a bit of confusion with this C# syntax.
I'm trying to assign an arbitrary delegate to a class.
I have a delegates defined as
delegate string stringCB(string s);
delegate int intCB(int i);
I have a class
class run_by_name {
public string name {get;set;}
public Delegate method {get;set;}
};
And I'm trying to instantiate it
run_by_name myfuc = new run_by_name(){
name = "my name",
method = new stringCB(string s) {
return " testing " + s;
};
};
I'm really not clear how to assign to a delegate when there's a return type. Also I'm not sure how to call that method later on syntactically.
Why I'm doing this? Well I'm just writing some code that follows a pattern I use in JS a lot for event handling, I'm just making an "object" I can assign arbitrary functions to for a generic event handler that's created rather than defined. (important)
Also, alternatives to using delegates are welcome. :)
EDIT: How I might use it later
I don't have that written yet but Im pretty sure I'll be doing this.
List<run_by_name> callbacks = new List<run_by_name>();
/* lets say this is initialized and filled at this point */
public object FindAndRunCallback(string Name, object input) {
foreach(var cb in callbacks) {
if( cb.name == Name )
return cb.method(input);
}
return null;
}
Here's the syntax you need to get your current code working:
method = new stringCB((string s) => {
return " testing " + s;
})
Or, using lambda expressions:
method = new stringCB(s =>" testing " + s)
You could later invoke the method like so:
string result = (string) myfuc.method.DynamicInvoke("hello");
Without knowing more about your use case, it's hard to recommend other approaches, but I'd recommend at least looking into the following:
Events: Your description sounds very close to the common pattern for events and event handlers in C#. Your event defines the delegate type that is used to handle it, and code elsewhere can subscribe to that event with methods that match that delegate type. By convention, people usually pass a sender object as the first parameter, and some strongly-typed EventArgs so that subscribers don't have to guess at what data is going to be available when the event fires.
Func<> and Action<> variants: As C# has evolved into a more functional language, programmers have trended away from using custom delegate types, and toward using the provided variants of Func<> and Action<>. Since the arguments are strongly-typed still, you get most of the advantages of a compiled language, but use a little "duck typing" for the actual function you pass around.
For example, you could give your class a generic type based on what types you expect your delegate to deal with:
class run_by_name<T> {
public string name {get;set;}
public Func<T, T> method {get;set;}
};
Then use it:
var myfuc = new run_by_name<string>{
name = "my name",
method = s =>" testing " + s
};
string result = myfuc.method("hello");
dynamic: This keyword allows you to late-bind actions on any object. You lose the advantages of a compiled language, but it improves interoperability with more dynamic languages immensely. For example, an object can be created via JSON, and you can access the properties on it without declaring a special type for that object, just like you can in Javascript.
For example, if you changed your method declaration to this:
public dynamic method {get;set;}
Then you could simply say:
string result = myfuc.method("hello");
You have seceral choices. the strinCB constructor expects a method, that takes a string parameter and returns a string. If you have an existing method, you can pass it's name to the constructor, or you can create an anonymous method wither by delegate syntax like this:
method = new stringCB(delegate(string s)
{
return " testing " + s;
})
Or using a lambda expression:
method = new stringCB(s =>
{
return " testing " + s;
})
Then you can call it like this: myfuc.method.DynamicInvoke(YourParameter);
Normally, calling a delegate's method is pretty easy like this:
Func<int, int, int> sum = (x, y) => x + y;
Console.WriteLine(sum(2,3)); // with the name of delegate
Console.WriteLine(sum.Invoke(2,3)); // or using Invoke method
But in this case, you need to use DynamicInvoke because the type of your property is Delegate.
Apart from that .NET Framework has some useful built-in delegate types, such as Func,Action and Predicate etc. You can use them instead of creating your own delegate as long as they satisfy your needs. For example in this case you can use a Func<string,string> instead of stringCB.

C#, instantiating a generic type - with variable type argument?

Code example:
void Foo(params object[] objects)
{
var entries = new List<IEntry>();
foreach(var o in objects)
{
var entry = new Entry<o.GetType()>(); // this doesn't work
entries.Add(entry);
}
...
}
Foo("hello", 5); // should fill entries with Entry<string> and Entry<int>
Why is that not possible? I guess I need to work with reflection instead? How to do that properly AND performant?
You just can't use C# generics the way you're trying to do in your snippet.
In order to use [C#] generics, the actual object type must be known at compile time.
You're trying to dynamically pass the object type as a type parameter. This is simply not possible.
Edit
Yes, it is possible to dynamically create generic objects using reflection. After all, generics is implemented both as a compile-time C# construct and as a .NET framework feature (as opposed to, say, Java, where it is only a compile-time feature based on Type Erasure). So, in .NET, through reflection, it is possible to implement the latter "bypassing" the former (which, again, would be impossible in Java).
But the OP clearly does not need that.
After all, entries is a List<IEntry>. IOW, the entries container does not "know" the concrete type of its elements (since it is bound to an interface). So, if each element to be add already implements IEntry, then this would be enough:
void Foo(params IEntry[] objects)
{
var entries = new List<IEntry>();
foreach(var o in objects)
{
entries.Add(o);
}
...
}
OTOH, if those objects do not implement IEntry, then the OP just need a pure, ordinary, old-school list of untyped objects:
void Foo(params object[] objects)
{
var entries = new List<object>();
foreach(var o in objects)
{
entries.Add(o);
}
...
}
So using reflection in order to dynamically create a generic container, even if possible, seems to be overkill for this particular use case.
You can do it with reflection
var entryType = typeof(Entry<>);
Type[] typeArgs = { o.GetType() };
var genericType = entryType.MakeGenericType(typeArgs);
IEntry entry = (IEntry)Activator.CreateInstance(genericType);
You need a function of the form:
Func<Type, IEntry>
I would suggest adding a static function to the parent of Foo like this:
public static IEntry Make(Type type)
Inside that function, feel free to add whatever code makes sense to you:
if (type == typeof(string))
{
return new StringEntry(); //Obviously some special logic based on the type.
}
else
{
//Default logic
return (IEntry) Activator.CreateInstance(typeof(Entry<>).MakeGenericType(type));
}

How can I create a MethodInfo from an Action delegate

I am trying to develop an NUnit addin that dynamically adds test methods to a suite from an object that contains a list of Action delegates. The problem is that NUnit appears to be leaning heavily on reflection to get the job done. Consequently, it looks like there's no simple way to add my Actions directly to the suite.
I must, instead, add MethodInfo objects. This would normally work, but the Action delegates are anonymous, so I would have to build the types and methods to accomplish this. I need to find an easier way to do this, without resorting to using Emit. Does anyone know how to easily create MethodInfo instances from Action delegates?
Have you tried Action's Method property? I mean something like:
MethodInfo GetMI(Action a)
{
return a.Method;
}
You don't need to "create" a MethodInfo, you can just retrieve it from the delegate :
Action action = () => Console.WriteLine("Hello world !");
MethodInfo method = action.Method
MethodInvoker CvtActionToMI(Action d)
{
MethodInvoker converted = delegate { d(); };
return converted;
}
Sorry, not what you wanted.
Note that all delegates are multicast, so there isn't guaranteed to be a unique MethodInfo. This will get you all of them:
MethodInfo[] CvtActionToMIArray(Action d)
{
if (d == null) return new MethodInfo[0];
Delegate[] targets = d.GetInvocationList();
MethodInfo[] converted = new MethodInfo[targets.Length];
for( int i = 0; i < targets.Length; ++i ) converted[i] = targets[i].Method;
return converted;
}
You're losing the information about the target objects though (uncurrying the delegate), so I don't expect NUnit to be able to successfully call anything afterwards.

C# Get Delegate (Func) implementation from concrete class via reflection?

Sorry for the poor explaination of the problem
Totally rewriting question
I have the following method:
public TReturn FindCached<TSearch, TReturn>(Func<TSearch, TReturn> searchMethod)
where TSearch : ISearchSpecification
where TReturn : class
{
SearchSpecification spec = new GetConcreteSearchSpecification<TSearch>();
//insert magic here to get an attribute from the method on
//the spec class that searchMethod invokes on the line below
return searchMethod(spec);
}
So I have a delegate (searchMethod) and an object (spec) that I want to invoke the delegate on. I want to inspect the object (spec) to find a custom attribute on the method that searchMethod will call when invoked.
Hope this is clearer.
Thanks
Assuming you meant searchMethod to be a variable of type Func<TSearch, TReturn> and mySearchSpec as some implementation of ISearchSpecification<TSearch>, then you are basically asking how to get attributes on a class.
For this, use something like:
object[] attrs = typeof(mySearchSpec).GetCustomAttributes(false);
Assuming that the mySearchSpec type is public, otherwise you may need a different overload for GetCustomAttributes
Addendum:
Based on your revised question, to get the attributes on a method on the actual type of spec used:
Type t = spec.GetType();
MethodInfo m = t.GetMethod("nameOfMethodToBeCalledHere");
object[] attrs = m.GetCustomAttributes(false);
Again, note that you may need overloads for GetMethod or GetCustomAttributes depending on the implementation of the actual class.
Note:
It does seem however like you might be asking for the method called in return searchMethod(spec);, but that is searchMethod and not some method on spec at all.
If you want attributes on searchMethod (nothing to do with spec):
MethodInfo m = searchMethod.Method;
object[] attrs = m.GetCustomAttributes(false);
I think that now covers all permutations of meaning...
This is quite a confusing question, let's see if I have it right:
You have a lambda function (which you describe as a delegate) called searchMethod.
You have a factory-pattern generated object called spec
So you have a method somewhere like this:
[MyCustomAttribute]
public RetClass MyMethod( SearchSpecification input ) {
return input.GetRetClass();
}
And you call this method with:
var result = FindCached( MyMethod );
And in FindCached you want to find MyCustomAttribute - in that case #jerryjvl's answer is right.
Your problem is that you could also do:
var result = FindCached( x => x.GetRetClass() );
I'm not sure from your description whether it's an attribute on the x.GetRetClass() that you actually want. In this case you need to take the lambda apart using expressions, but I wouldn't recommend it - a more complex lambda declaration will result in an anonymous delegate, which is a black-box when you try to parse it at run time.
Instead, as you're using reflection anyway, it might be easier to pass the name of the method that you want instead of the delegate reference:
var result = FindCached( "GetRetClass" );
I ran into a similar situation, jerryjvl's answer explained exactly what I wanted.
I wanted to create a generic profiling method, where I could time how long some method took to run, and retrieve the name of the method using reflection for logging purposes.
The MethodInfo was the key.
Where I have a method like:
public static bool TimeMethod(Func<bool> someMethod)
And then later I want to dynamically get it's name or some attributes off it.
MethodInfo m = someMethod.Method;
object[] attrs = m.GetCustomAttributes(typeof(MonitoringDescriptionAttribute), true);
string name = m.Name;
Cheers

Why can't I do this with implicit types in C#?

var x = new { a = "foobar", b = 42 };
List<x.GetType()> y;
Is there a different way to do what I want to do here?
If there's not, I don't really see all that much point in implicit types...
x.GetType() is a method call, evaluated at execution time. It therefore can't be used for a compile-time concept like the type of a variable. I agree that occasionally it would be quite handy to be able to do something similar (specifying the compile-time type of a variable as a type argument elsewhere), but currently you can't. I can't say I regularly miss it though.
However, you can do:
var x = new { a = "foobar", b = 42 };
var y = new[] { x };
var z = y.ToList();
You could also write a simple extension method to create a list generically:
public static List<T> InList<T>(this T item)
{
return new List<T> { item };
}
(Pick a different name if you want :)
Then:
var x = new { a = "foobar", b = 42 };
var y = x.InList();
As Marc shows, it doesn't actually have to be an extension method at all. The only important thing is that the compiler can use type inference to work out the type parameter for the method so that you don't have to try to name the anonymous type.
Implicitly typed local variables are useful for a variety of reasons, but they're particularly useful in LINQ so that you can create an ad-hoc projection without creating a whole new type explicitly.
There are ways of doing this with a generic method:
public static List<T> CreateList<T>(T example) {
return new List<T>();
}
...
var list = CreateList(x);
or by creating a list with data and then emptying it...

Categories

Resources