How to define a delegate using Delegate.CreateDelegate instead of Func<>? - c#

I have a method and two delegate like below. It is running in this way. But I want to use Delegate.CreateInstance. The types of the dx and the dy must be Func<IEnumerable<Foo>>. Like below the fx and fy. They must not be Func<int, IEnumerable<Foo>>.
public class Test {
private IEnumerable<T> CreateItems<T>(int count) where T : class
{
for (int i = 0; i < count; i++)
{
yield return (T)Activator.CreateInstance(typeof(T), i.ToString());
}
}
public List<T> TestMethod<T>(int i = 1) where T : class
{
return CreateItems<T>(i).ToList();
}
public void TestRun()
{
const int Count = 5;
Func<IEnumerable<Foo>> fx = () => this.TestMethod<Foo>(Count);
Func<IEnumerable<Foo>> fy = () => this.TestMethod<Foo>();
var lfx = fx.Invoke();
var lfy = fy.Invoke();
var dx = Delegate.CreateDelegate( ?? );
var dy = Delegate.CreateDelegate( ?? );
var ldx = dx.DynamicInvoke();
var ldy = dy.DynamicInvoke();
}
}

If you want the type to be Func<IEnumerable<Foo>>, then you cannot create that directly via Delegate.CreateDelegate since they require two parameters: the instance (aka this), and the integer i. Even the form shown in fx has an i - it just happens to be supplied by the compiler. If TestMethod didn't take parameters, it could be done via:
var dy = (Func<IEnumerable<Foo>>) Delegate.CreateDelegate(
typeof(Func<IEnumerable<Foo>>),
this,
GetType().GetMethod("TestMethod").MakeGenericMethod(typeof(Foo))
);
To do this (partial application) dynamically, you would need to create a type that has the instance (this), the value to inject (the i), and a method that calls TestMethod<Foo> with those values. Which is exactly what the compiler does for you here:
Func<IEnumerable<Foo>> fx = () => this.TestMethod<Foo>(Count);
That basically creates:
internal class <>_squiggle {
public Test #this;
public IEnumerable<Foo> Method() {
return #this.TestMethod<Foo>(5);
}
}
and:
var capture = new <>_squiggle { #this = this };
var fx = new Func<IEnumerable<Foo>>(capture.Method);

That's impossible. There is no way you can fit an instance method with signature A F(X x) into a Func<A> directly.
It's possible to bind the first parameter of a method into the delegate directly, but no additional parameters. In your case the instance this is that first parameter, and you can't bind a value for i.
I guess your misunderstanding is how parameters with default values work. They're still parameters that need to be filled in by the caller. It's just that the C# compiler does that for you.
You will need a wrapper of some kind with the correct signature. That can be a lambda, or some other helper method. In your case I'd overload the method TestMethod instead of using a default parameter.

Related

var is not detecting result of method with dynamic input

I have the following problem
private int GetInt(dynamic a)
{
return 1;
}
private void UsingVar()
{
dynamic a = 5;
var x = GetInt(a);
}
But x is still dynamic.
I don't understand why.
Since your argument a in the GetInt method call have the type dynamic, so the overload resolution occurs at run time instead of at compile time.
Based on this:
Overload resolution occurs at run time instead of at compile time if one or more of the arguments in a method call have the type dynamic, or if the receiver of the method call is of type dynamic.
Actually by using the dynamic you are using the late binding (defers to later), and it means, the compiler can't verify it because it won't use any static type analysis anymore.
The solution would be using a cast like this:
var x = (int)GetInt(a);
The following is how the compiler is treating your code:
private void UsingVar()
{
object arg = 5;
if (<>o__2.<>p__0 == null)
{
Type typeFromHandle = typeof(C);
CSharpArgumentInfo[] array = new CSharpArgumentInfo[2];
array[0] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null);
array[1] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
<>o__2.<>p__0 = CallSite<Func<CallSite, C, object, object>>
.Create(Microsoft.CSharp.RuntimeBinder.Binder
.InvokeMember(CSharpBinderFlags.InvokeSimpleName, "GetInt", null, typeFromHandle, array));
}
object obj = <>o__2.<>p__0.Target(<>o__2.<>p__0, this, arg);
}

dynamic type does not contain a definition for 'property', error? [duplicate]

My situation is very simple. Somewhere in my code I have this:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
//How to do this?
if (myVariable.MyProperty.Exists)
//Do stuff
So, basically my question is how to check (without throwing an exception) that a certain property is available on my dynamic variable. I could do GetType() but I'd rather avoid that since I don't really need to know the type of the object. All that I really want to know is whether a property (or method, if that makes life easier) is available. Any pointers?
I think there is no way to find out whether a dynamic variable has a certain member without trying to access it, unless you re-implemented the way dynamic binding is handled in the C# compiler. Which would probably include a lot of guessing, because it is implementation-defined, according to the C# specification.
So you should actually try to access the member and catch an exception, if it fails:
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
try
{
var x = myVariable.MyProperty;
// do stuff with x
}
catch (RuntimeBinderException)
{
// MyProperty doesn't exist
}
I thought I'd do a comparison of Martijn's answer and svick's answer...
The following program returns the following results:
Testing with exception: 2430985 ticks
Testing with reflection: 155570 ticks
void Main()
{
var random = new Random(Environment.TickCount);
dynamic test = new Test();
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
TestWithException(test, FlipCoin(random));
}
sw.Stop();
Console.WriteLine("Testing with exception: " + sw.ElapsedTicks.ToString() + " ticks");
sw.Restart();
for (int i = 0; i < 100000; i++)
{
TestWithReflection(test, FlipCoin(random));
}
sw.Stop();
Console.WriteLine("Testing with reflection: " + sw.ElapsedTicks.ToString() + " ticks");
}
class Test
{
public bool Exists { get { return true; } }
}
bool FlipCoin(Random random)
{
return random.Next(2) == 0;
}
bool TestWithException(dynamic d, bool useExisting)
{
try
{
bool result = useExisting ? d.Exists : d.DoesntExist;
return true;
}
catch (Exception)
{
return false;
}
}
bool TestWithReflection(dynamic d, bool useExisting)
{
Type type = d.GetType();
return type.GetProperties().Any(p => p.Name.Equals(useExisting ? "Exists" : "DoesntExist"));
}
As a result I'd suggest using reflection. See below.
Responding to bland's comment:
Ratios are reflection:exception ticks for 100000 iterations:
Fails 1/1: - 1:43 ticks
Fails 1/2: - 1:22 ticks
Fails 1/3: - 1:14 ticks
Fails 1/5: - 1:9 ticks
Fails 1/7: - 1:7 ticks
Fails 1/13: - 1:4 ticks
Fails 1/17: - 1:3 ticks
Fails 1/23: - 1:2 ticks
...
Fails 1/43: - 1:2 ticks
Fails 1/47: - 1:1 ticks
...fair enough - if you expect it to fail with a probability with less than ~1/47, then go for exception.
The above assumes that you're running GetProperties() each time. You may be able to speed up the process by caching the result of GetProperties() for each type in a dictionary or similar. This may help if you're checking against the same set of types over and again.
Maybe use reflection?
dynamic myVar = GetDataThatLooksVerySimilarButNotTheSame();
Type typeOfDynamic = myVar.GetType();
bool exist = typeOfDynamic.GetProperties().Where(p => p.Name.Equals("PropertyName")).Any();
Just in case it helps someone:
If the method GetDataThatLooksVerySimilarButNotTheSame() returns an ExpandoObject you can also cast to a IDictionary before checking.
dynamic test = new System.Dynamic.ExpandoObject();
test.foo = "bar";
if (((IDictionary<string, object>)test).ContainsKey("foo"))
{
Console.WriteLine(test.foo);
}
The two common solutions to this include making the call and catching the RuntimeBinderException, using reflection to check for the call, or serialising to a text format and parsing from there. The problem with exceptions is that they are very slow, because when one is constructed, the current call stack is serialised. Serialising to JSON or something analogous incurs a similar penalty. This leaves us with reflection but it only works if the underlying object is actually a POCO with real members on it. If it's a dynamic wrapper around a dictionary, a COM object, or an external web service, then reflection won't help.
Another solution is to use IDynamicMetaObjectProvider to get the member names as the DLR sees them. In the example below, I use a static class (Dynamic) to test for the Age field and display it.
class Program
{
static void Main()
{
dynamic x = new ExpandoObject();
x.Name = "Damian Powell";
x.Age = "21 (probably)";
if (Dynamic.HasMember(x, "Age"))
{
Console.WriteLine("Age={0}", x.Age);
}
}
}
public static class Dynamic
{
public static bool HasMember(object dynObj, string memberName)
{
return GetMemberNames(dynObj).Contains(memberName);
}
public static IEnumerable<string> GetMemberNames(object dynObj)
{
var metaObjProvider = dynObj as IDynamicMetaObjectProvider;
if (null == metaObjProvider) throw new InvalidOperationException(
"The supplied object must be a dynamic object " +
"(i.e. it must implement IDynamicMetaObjectProvider)"
);
var metaObj = metaObjProvider.GetMetaObject(
Expression.Constant(metaObjProvider)
);
var memberNames = metaObj.GetDynamicMemberNames();
return memberNames;
}
}
Denis's answer made me think to another solution using JsonObjects,
a header property checker:
Predicate<object> hasHeader = jsonObject =>
((JObject)jsonObject).OfType<JProperty>()
.Any(prop => prop.Name == "header");
or maybe better:
Predicate<object> hasHeader = jsonObject =>
((JObject)jsonObject).Property("header") != null;
for example:
dynamic json = JsonConvert.DeserializeObject(data);
string header = hasHeader(json) ? json.header : null;
Well, I faced a similar problem but on unit tests.
Using SharpTestsEx you can check if a property existis. I use this testing my controllers, because since the JSON object is dynamic, someone can change the name and forget to change it in the javascript or something, so testing for all properties when writing the controller should increase my safety.
Example:
dynamic testedObject = new ExpandoObject();
testedObject.MyName = "I am a testing object";
Now, using SharTestsEx:
Executing.This(delegate {var unused = testedObject.MyName; }).Should().NotThrow();
Executing.This(delegate {var unused = testedObject.NotExistingProperty; }).Should().Throw();
Using this, i test all existing properties using "Should().NotThrow()".
It's probably out of topic, but can be usefull for someone.
Following on from the answer by #karask, you could wrap the function as a helper like so:
public static bool HasProperty(ExpandoObject expandoObj,
string name)
{
return ((IDictionary<string, object>)expandoObj).ContainsKey(name);
}
For me this works:
if (IsProperty(() => DynamicObject.MyProperty))
; // do stuff
delegate string GetValueDelegate();
private bool IsProperty(GetValueDelegate getValueMethod)
{
try
{
//we're not interesting in the return value.
//What we need to know is whether an exception occurred or not
var v = getValueMethod();
return v != null;
}
catch (RuntimeBinderException)
{
return false;
}
catch
{
return true;
}
}
If you control the type being used as dynamic, couldn't you return a tuple instead of a value for every property access? Something like...
public class DynamicValue<T>
{
internal DynamicValue(T value, bool exists)
{
Value = value;
Exists = exists;
}
T Value { get; private set; }
bool Exists { get; private set; }
}
Possibly a naive implementation, but if you construct one of these internally each time and return that instead of the actual value, you can check Exists on every property access and then hit Value if it does with value being default(T) (and irrelevant) if it doesn't.
That said, I might be missing some knowledge on how dynamic works and this might not be a workable suggestion.
If your use case is to convert an api response, carrying about only a few fields, you can use this:
var template = new { address = new { street = "" } };
var response = JsonConvert.DeserializeAnonymousType(await result.Content.ReadAsStringAsync(), template);
string street = response?.address?.street;
Here is the other way:
using Newtonsoft.Json.Linq;
internal class DymanicTest
{
public static string Json = #"{
""AED"": 3.672825,
""AFN"": 56.982875,
""ALL"": 110.252599,
""AMD"": 408.222002,
""ANG"": 1.78704,
""AOA"": 98.192249,
""ARS"": 8.44469
}";
public static void Run()
{
dynamic dynamicObject = JObject.Parse(Json);
foreach (JProperty variable in dynamicObject)
{
if (variable.Name == "AMD")
{
var value = variable.Value;
}
}
}
}
In my case, I needed to check for the existence of a method with a specific name, so I used an interface for that
var plugin = this.pluginFinder.GetPluginIfInstalled<IPlugin>(pluginName) as dynamic;
if (plugin != null && plugin is ICustomPluginAction)
{
plugin.CustomPluginAction(action);
}
Also, interfaces can contain more than just methods:
Interfaces can contain methods, properties, events, indexers, or any
combination of those four member types.
From: Interfaces (C# Programming Guide)
Elegant and no need to trap exceptions or play with reflexion...
I know this is really old post but here is a simple solution to work with dynamic type in c#.
can use simple reflection to enumerate direct properties
or can use the object extention method
or use GetAsOrDefault<int> method to get a new strongly typed object with value if exists or default if not exists.
public static class DynamicHelper
{
private static void Test( )
{
dynamic myobj = new
{
myInt = 1,
myArray = new[ ]
{
1, 2.3
},
myDict = new
{
myInt = 1
}
};
var myIntOrZero = myobj.GetAsOrDefault< int >( ( Func< int > )( ( ) => myobj.noExist ) );
int? myNullableInt = GetAs< int >( myobj, ( Func< int > )( ( ) => myobj.myInt ) );
if( default( int ) != myIntOrZero )
Console.WriteLine( $"myInt: '{myIntOrZero}'" );
if( default( int? ) != myNullableInt )
Console.WriteLine( $"myInt: '{myNullableInt}'" );
if( DoesPropertyExist( myobj, "myInt" ) )
Console.WriteLine( $"myInt exists and it is: '{( int )myobj.myInt}'" );
}
public static bool DoesPropertyExist( dynamic dyn, string property )
{
var t = ( Type )dyn.GetType( );
var props = t.GetProperties( );
return props.Any( p => p.Name.Equals( property ) );
}
public static object GetAs< T >( dynamic obj, Func< T > lookup )
{
try
{
var val = lookup( );
return ( T )val;
}
catch( RuntimeBinderException ) { }
return null;
}
public static T GetAsOrDefault< T >( this object obj, Func< T > test )
{
try
{
var val = test( );
return ( T )val;
}
catch( RuntimeBinderException ) { }
return default( T );
}
}
As ExpandoObject inherits the IDictionary<string, object> you can use the following check
dynamic myVariable = GetDataThatLooksVerySimilarButNotTheSame();
if (((IDictionary<string, object>)myVariable).ContainsKey("MyProperty"))
//Do stuff
You can make a utility method to perform this check, that will make the code much cleaner and re-usable

C# run public void functions in loop

I have list of public void function that get one parameter to execute and I want to use loop to do it,
I do not know how to do this, can you advise me?
I thought to insert the names of mt functions to arr and than run in loop
something like this
string[] s1 = new string[3] {"func1", "func2", "func3"};
for(int i=0;i<s1.lengh;i++)
here I want to call the function ... how can I do it?
Do you have better offer?
Thanks.
You can pass functions as parameters / arguments by the use of delegates:
Action<T> action1 = func1;
Action<T> action2 = func2;
where T is the type of the parameter (e.g. int, string)
You can then run these referenced functions by calling
action1(t);
action2(t);
where t is the parameter for your function.
To make this example useful, consider creating a list of actions:
List<Action<T>> actions = new List<Action<T>>();
actions.Add(action1); actions.Add(action2);
foreach (Action<T> action in actions)
{
var t = param; // Replace param with the input parameter
action(t);
}
Of course, you must also have
using System;
at the top of your code file to reference Action.
See also the MSDN documentation on the Action delegate: http://msdn.microsoft.com/en-us/library/018hxwa8.aspx
Your first option is to use delegates (assuming the argument is an integer):
var s1 = new Action<int>[3] { a => func1(a), a => func2(a), a => func3(a) }; // without quotes it creates a function pointer
for(int i=0;i<s1.Length;i++)
s1[i](parameter); // call the delegate
If you do not know the function names at compile time, use reflection to call the method:
var s1 = new string[3] {"func1", "func2", "func3"};
for(int i=0;i<s1.Length;i++)
this.GetType().GetMethod(s1[i]).Invoke(this, new object[] { parameter });
Note the this.GetType() in the second sample - if the methods are defined on another type you will most probably use typeof(OtherType) instead.
Use a delegate. For example, to invoke a method that takes one parameter and returns no value (i.e. returns void), use the Action<T> delegate. Assuming that you want them all to accept the same parameter type, it would look a bit like this:
public void Action1(int x) { ... }
public void Action2(int x) { ... }
public void Action3(int x) { ... }
...
Action<int>[] actions = new Action<int>[] { Action1, Action2, Action3 }
for (int i = 0; i < actions.Length; i++)
{
actions[i](i); // Invoke the delegate with (...)
}
Further Reading
Delegates (C# Programming Guide)
I believe what you are wanting to do could be accomplished via a collection of actions.
Assuming the type of parameter for each function is integer, here's how that could look:
List<Action<int>> functions = new List<Action<int>> {func1, func2, func3};
int i = 5;
foreach (Action<int> f in functions)
{
f(i);
}
EDIT: updated per updated OP that specifies the looping should only be over each of the functions.
var list = new List<Action<MyParameterType>>() {func1, func2, func3};
foreach(var func in list)
{
func(someValue);
}
string[] s1 = new string[3] {"func1", "func2", "func3"};
for(int i=0;i<s1.lengh;i++)
List<string, Func<string>> functionList = new List<string, Func<string>>();
functionList.Add(s1[0], ()=>{return "You called func1!";});
functionList.Add(s1[1], ()=>{return "You called func2!";});
functionList.Add(s1[2], ()=>{return "You called func3!";});
for(int i=0;i<s1.length;i++)
{
string retVal = functionList[s1[i]].Invoke();
}

Storing and calling generically-typed delegates

What I'm looking for is probably not going to be possible without resorting to reflection. If that's the case, I'd still want to know the best way to pull it off.
Essentially, this is what I want my code to look like:
var instance = new MyClass();
instance.Add<int, string>(x => x.ToString());
instance.Add<string, Warehouse>(x => Warehouse.LookupByName(x));
instance.Add<Warehouse, IList<Supplier>>(x => x.Suppliers());
instance.Chain(3); // should call each lambda expression in turn
My question is, how can I store these delegates, each with a different signature, in a list in MyClass? And how can I call them later on when I want to, using the return value from each one as the input parameter to the next one?
The inside of MyClass may very well be a mess of List's and all that. But I'm not even sure where to start on this.
(Originally, I wanted to call new MyClass<int, string, Warehouse, IList<Supplier>>(). However, since there's no "type parameter array", I gave up on that approach.)
Well, you could store them all as Delegate - but the tricky thing is invoking them later.
If you're able to validate that the next delegate at any time is of the right type, e.g. by holding a Type reference for "the current output" you could always store a List<Func<object, object>> and make your Add method something like:
public void Add<TIn, TOut>(Func<TIn, TOut> func)
{
// TODO: Consider using IsAssignableFrom etc
if (currentOutputType != typeof(TIn))
{
throw new InvalidOperationException(...);
}
list.Add(o => (object) func((TIn) o));
currentOutputType = typeof(TOut);
}
Then to invoke them all:
object current = ...; // Wherever
foreach (var func in list)
{
current = func(current);
}
The Linq Select statement essentially does this...
var temp = instance.Select(x => x.ToString())
.Select(x => WareHouse.LookupByName(x))
.Select(x=> x.Suppliers());
List<List<Suppliers>> = temp.ToList(); //Evaluate statements
You can also store each intermediate Select call as an Enumerable to have the stated method you use in the OP.
class Program
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Add<int, string>(i => i.ToString());
instance.Add<string, int>(str => str.Length);
instance.Add<int, int>(i => i*i);
Console.WriteLine(instance.Chain(349));
Console.ReadLine();
}
}
public class MyClass
{
private IList<Delegate> _Delegates = new List<Delegate>();
public void Add<InputType, OutputType>(Func<InputType, OutputType> action)
{
_Delegates.Add(action);
}
public object Chain<InputType>(InputType startingArgument)
{
object currentInputArgument = startingArgument;
for (var i = 0; i < _Delegates.Count(); ++i)
{
var action = _Delegates[i];
currentInputArgument = action.DynamicInvoke(currentInputArgument);
}
return currentInputArgument;
}
}
If you want compile time type checking, what you are doing sounds suspiciously like plain old generic delegates. Assuming that there is some value to storing the individual functions that were Added (other than the Int to String conversion) and composing them later, you can do something like this:
var lookupWarehouseByNumber = new Func<int, Warehouse>(i => Warehouse.LookupByName(i.ToString()));
var getWarehouseSuppliers = new Func<Warehouse, IEnumerable<Supplier>>(w => w.Suppliers);
var getWarehouseSuppliersByNumber = new Func<int, IEnumerable<Supplier>>(i => getWarehouseSuppliers(lookupWarehouseByNumber(i)));

C# - Generic type function is trying to assign result to System.Func(specified type) when a function with parameters is passed in

I'm using a class with a method that looks like the following:
public static T Get<T>(string key, Func<T> method)
{
//do stuff
var obj = method.Invoke();
return (T)obj
}
It works great if it I call it like this:
var x = Get<string>("mykey", test);
Where test is a function that has no parameters and returns a string. However, things break as soon as test has parameters. If I try:
var x = Get<string>("mykey", test(myparam));
I get the error "Argument type "String" is not assignable to parameter type "System.Func< string >".
I know the addition of (myparam) is the problem, but I'm not sure how it should be fixed. Is the issue with how the library's function is written or with how I'm trying to pass in the parameter?
var x = Get<string>("mykey", () => test(myparam));
You can call it like in the following sample code:
Get("mykey", () => test(myparam))
public static T Get<T>(string key, Func<T> method)
{
//do stuff
var obj = method.Invoke();
return (T)obj;
}
void Xyz()
{
int myparam = 0;
var x = Get("mykey", () => test(myparam)); // <string> is not needed
}
double test(int i)
{
return 0.0;
}
You need to curry the parameter by passing a lambda expression that takes no parameters and calls your function with a parameter from elsewhere:
var x = Get<string>("mykey", () => test(myparam));
It's how you're passing the parameter. test(myparam) has type String, and you need to pass a function which returns a String. You can make one with very little effort using a lambda expression:
var x = Get<string>("mykey", () => test(myparam));
The lambda expression () => foo creates a function which, when called, executes and returns foo.
You need to change your Func definition to define the input params thus:
Func<T,T1,T2,T3> method

Categories

Resources