I find myself in the situation requiring this
public static void Fill(this SomeClass c, params out object[] p)
and calling it as
c.Fill(out i, out i2, out sz, out i3, out sz2);
However i get the error error CS1611: The params parameter cannot be declared as ref or out
How can i pass in variable length arguments and make them writeable? All of these are a mixture of ints and strings
You can't have it treat the arguments as out (or ref) and make use of the params feature at the same time. It simply doesn't work. The best you can do is to create an array parameter, make the array out, declare an array variable and call the method passing the array, then inspect each element manually by index.
Foo(out object[] data) {...}
object[] result;
Foo(out result);
// look at result[0], result[1], result[2] etc
So: you cannot do what you want. Even if you could, ref / out never work unless there is an exact match between data type, so it would still have to be:
object o1, o2, o3, o4;
Foo(out o1, out o2, out o3, out o4);
// cast o1, o2, o3, o4
Which still isn't what you want.
There is no technical need for out here. This works:
void Fill(object[] p)
{
p[0] = 1;
p[1] = 42;
p[2] = "Hello";
p[3] = -1;
p[4] = "World";
}
object[] p = new object[5];
foo.Fill(p);
i = (int)p[0];
i2 = (int)p[1];
sz = (string)p[2];
i3 = (int)p[3];
sz2 = (string)p[4];
You could return your values as Tuple:
(define your own tuple class if you're not using .NET4.0)
static Tuple<int, string> Fill()
{
return new Tuple(42, "Hello World");
}
and then define extension methods to unpack tuples:
public static class TupleExtensions
{
public static void Unpack<T1, T2>(
this Tuple<T1, T2> tuple,
out T1 item1,
out T2 item2)
{
item1 = tuple.Item1;
item2 = tuple.Item2;
}
}
Then you can write this:
int i;
string sz;
foo.Fill().Unpack(out i, out sz);
1) If you can avoid the need to get the values in declared variables, then passing the array and populating it is the best option, as shown by dtb's answer.
2) Otherwise you can have a simple wrapper for your variable.
public class Wrapper //or may be generic?
{
public object Value { get; set; }
public Wrapper(object value)
{
Value = value;
}
}
Now you can call
var i = new Wrapper(0), i2 = new Wrapper(0), i3 = new Wrapper(0);
c.Fill(i, i2, i3);
i.Value //your value here
public static void Fill(this SomeClass c, params Wrapper[] p)
{
for (int i = 0; i < p.Length; i++)
{
p[i].Value = 1; //assigning
}
}
You will have to deal with Value property after calling Fill method.
3) You can make use of closure. Something like the Ref<T> class implemented as shown:
public static class Ref
{
public static Ref<T>[] Create<T>(params Expression<Func<T>>[] getters)
{
return getters.Select(Create).ToArray();
}
public static Ref<T> Create<T>(Expression<Func<T>> getter)
{
return new Ref<T>(getter);
}
}
public sealed class Ref<T>
{
readonly Func<T> getter;
readonly Action<T> setter;
public Ref(Expression<Func<T>> getter)
{
var output = getter.Body;
var input = Expression.Parameter(output.Type); //or hardcode typeof(T)
var assign = Expression.Assign(output, input);
var setter = Expression.Lambda<Action<T>>(assign, input);
this.getter = getter.Compile();
this.setter = setter.Compile();
}
public T Value
{
get { return getter(); }
set { setter(value); }
}
}
public static void Fill(this SomeClass c, params Ref<object>[] p)
//assign inside
object i = 0, i2 = 0, i3 = 0;
c.Fill(Ref.Create(() => i, () => i2, () => i3));
//i, i2 etc changed
Few things to note:
All the above approaches are basically ref approaches, compiler doesn't simply force assigning value of parameters inside the method before the control leaves as in the case of out which is your question, but as far as I know out is not possible here.
I like the first one, simple, and conventional. If not possible my vote is for 3rd approach.
As others have talked about, you can only pass the exact same type as ref/out parameters. So if your method by definition takes arbitrary references of object type, you have to declare even your variables as object locally. In the last approach, you can make the whole thing generic like by changing parameter type to Ref<T> from Ref<object> but that means your all local variables should also be one T.
You can use a dictionary structure to cache Ref<T> to avoid recompiling same trees.
The same implementation can be used to pass properties and variables as method arguments or return values by reference.
As others have said, you can't use params and out together. You have to construct an array at the call site.
This is because params tells the compiler to do the same thing - construct an array from the specified arguments. Unfortunately, when the compiler creates the array, you don't get a reference to it; even if the variable is written with a new array, you can never get to it.
I would guess you are asking for a thin metal ruler. What problem are you trying to solve with this mechanism?
I think I might have an answer to your question; Consider the following code snippet, with the main "InvokeMemberMethod" function doing the job you ask for. I encountered the same problem as you and came up with this solution:
Note: the "isOutXX" parameter specifies if the preceeding parameter is an "out" parameter.
static object InvokeMemberMethod(object currentObject, string methodName, int argCount,
ref object arg1, bool isOut1,
ref object arg2, bool isOut2,
ref object arg3, bool isOut3,
ref object arg4, bool isOut4,
ref object arg5, bool isOut5,
ref object arg6, bool isOut6)
{
if (string.IsNullOrEmpty(methodName))
{
throw new ArgumentNullException("methodName");
}
if (currentObject == null)
{
throw new ArgumentNullException("currentObject");
}
Type[] argTypes = null;
object[] args = null;
if (argCount > 0)
{
argTypes = new Type[argCount];
args = new object[argCount];
argTypes[0] = arg1.GetType();
if (isOut1)
{
argTypes[0] = arg1.GetType().MakeByRefType();
}
args[0] = arg1;
if (argCount == 2)
{
argTypes[1] = arg2.GetType();
if (isOut2)
{
argTypes[1] = arg2.GetType().MakeByRefType();
}
args[1] = arg2;
}
if (argCount == 3)
{
argTypes[2] = arg3.GetType();
if (isOut3)
{
argTypes[2] = arg3.GetType().MakeByRefType();
}
args[2] = arg3;
}
if (argCount == 4)
{
argTypes[3] = arg4.GetType();
if (isOut4)
{
argTypes[3] = arg4.GetType().MakeByRefType();
}
args[3] = arg4;
}
if (argCount == 5)
{
argTypes[4] = arg5.GetType();
if (isOut5)
{
argTypes[4] = arg5.GetType().MakeByRefType();
}
args[4] = arg5;
}
if (argCount == 6)
{
argTypes[5] = arg6.GetType();
if (isOut6)
{
argTypes[5] = arg6.GetType().MakeByRefType();
}
args[5] = arg6;
}
}
MethodInfo methodInfo = currentObject.GetType().GetMethod(methodName, argTypes);
int retryCount = 0;
object ret = null;
bool success = false;
do
{
try
{
//if (methodInfo is MethodInfo)
{
Type targetType = currentObject.GetType();
ParameterInfo[] info = methodInfo.GetParameters();
ParameterModifier[] modifier = new ParameterModifier[] { new ParameterModifier(info.Length) };
int i = 0;
foreach (ParameterInfo paramInfo in info)
{
if (paramInfo.IsOut)
{
modifier[0][i] = true;
}
i++;
}
ret = targetType.InvokeMember(methodName, BindingFlags.InvokeMethod, null, currentObject, args,
modifier, null, null);
//ret = ((MethodInfo)methodInfo).Invoke(currentObject, args,);
success = true;
}
//else
{
// log error
}
}
catch (TimeoutException ex)
{
}
catch (TargetInvocationException ex)
{
throw;
}
retryCount++;
} while (!success && retryCount <= 1);
if (argCount > 0)
{
if (isOut1)
{
arg1 = args[0];
}
if (argCount == 2)
{
if (isOut2)
{
arg2 = args[1];
}
}
if (argCount == 3)
{
if (isOut3)
{
arg3 = args[2];
}
}
if (argCount == 4)
{
if (isOut4)
{
arg4 = args[3];
}
}
if (argCount == 5)
{
if (isOut5)
{
arg5 = args[4];
}
}
if (argCount == 6)
{
if (isOut6)
{
arg6 = args[5];
}
}
}
return ret;
}
public int OutTest(int x, int y)
{
return x + y;
}
public int OutTest(int x, out int y)
{
y = x + 1;
return x+2;
}
static void Main(string[] args)
{
object x = 1, y = 0, z = 0;
Program p = new Program();
InvokeMemberMethod(p, "OutTest", 2,
ref x, false,
ref y, true,
ref z, false,
ref z, false,
ref z, false,
ref z, false);
}
You could pass an array by ref.
Edit:
This would of course change your calling method:
object[] array = new object[] { i, i2, sz, i3, sz2 };
c.Fill(ref array);
I don't imagine the original questioner needs this answer 11 years later, but I found this old question when searching for an overlapping requirement... and thinking through the answer to this question made me realise why my related one wouldn't work very neatly.
For this question, it was implied that the caller needs to communicate the number of parameters and their types to the Fill(...) function - how else does it match up the types to the calling site?
The intended syntax at the calling site could be achieved like this:
public class SomeClass { }
public static void Fill(this SomeClass c, Type[] outputTypes, out object[] p)
{
p = new object[outputTypes.Length];
// TODO: implementation to fill array with values of the corresponding types.
}
// this overload can be removed if "fill" of an empty array is meaningless.
public static void Fill(this SomeClass c)
{
c.Fill(new Type[0], out _);
}
public static void Fill<T>(this SomeClass c, out T r1)
{
c.Fill(new[] { typeof(T) }, out var p);
r1 = (T)p[0];
}
public static void Fill<T1, T2>(this SomeClass c, out T1 r1, out T2 r2)
{
c.Fill(new[] { typeof(T1), typeof(T2) }, out var p);
r1 = (T1)p[0];
r2 = (T2)p[1];
}
// ... extend as required depending on maximum number of out parameters that might be needed
// in particular the 5-parameter version is included in this sample to make OP's sample code line work.
public static void Fill<T1, T2, T3, T4, T5>(this SomeClass c, out T1 r1, out T2 r2, out T3 r3, out T4 r4, out T5 r5)
{
c.Fill(new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4), typeof(T5) }, out var p);
r1 = (T1)p[0];
r2 = (T2)p[1];
r3 = (T3)p[2];
r4 = (T4)p[3];
r5 = (T5)p[4];
}
public static void someFunction()
{
SomeClass c = new SomeClass();
int i, i2, i3;
string sz, sz2;
// the line below is exactly as shown in question.
c.Fill(out i, out i2, out sz, out i3, out sz2);
}
Related
I have a list public List<ArticleWarehouseLocations> ArticleWarehouseLocationsList. In this list I have a property called Position.
`Swap<long>(ref ArticleWarehouseLocationsList[currentIndex].Position, ref ArticleWarehouseLocationsList[currentIndex - 1].Position);`
public void Swap<T>(ref T lhs, ref T rhs)
{
T temp = lhs;
lhs = rhs;
rhs = temp;
}
I'm trying to do something like this. It's giving me an error property or index may not be passed as ref or out.
I can use a local variable and assign it the value and use it but I'm looking for a global solution.
What you can do is make the property return by reference:
class Obj {
private long pos;
public ref long Position { get { return ref pos; } }
}
static void Main(string[] args)
{
Obj[] arr = new Obj[2] { new Obj(), new Obj() };
arr[0].Position = 10;
arr[1].Position = 20;
int index = 0;
WriteLine($"{arr[index].Position}, {arr[index+1].Position}");
Swap<long>(ref arr[index].Position, ref arr[index+1].Position);
WriteLine($"{arr[index].Position}, {arr[index+1].Position}");
}
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/ref-returns
I believe the tuple swap (x, y) = (y, x) proposed in comments is the way to go, but wanted to share yet another aproach with LINQ Expressions (a bit too long for a comment, so posting as an answer)
public static void SwapProperties<T>(T lhs, T rhs, Expression<Func<T, object>> propExpression)
{
var prop = GetPropertyInfo(propExpression);
var lhsValue = prop.GetValue(lhs);
var rhsValue = prop.GetValue(rhs);
prop.SetValue(lhs, rhsValue);
prop.SetValue(rhs, lhsValue);
}
private static PropertyInfo GetPropertyInfo<T>(Expression<Func<T, object>> propExpression)
{
PropertyInfo prop;
if (propExpression.Body is MemberExpression memberExpression)
{
prop = (PropertyInfo) memberExpression.Member;
}
else
{
var op = ((UnaryExpression) propExpression.Body).Operand;
prop = (PropertyInfo) ((MemberExpression) op).Member;
}
return prop;
}
class Obj
{
public long Position { get; set; }
public string Name { get; set; }
}
public static void Main(string[] args)
{
var a1 = new Obj()
{
Position = 10,
Name = "a1"
};
var a2 = new Obj()
{
Position = 20,
Name = "a2"
};
SwapProperties(a1, a2, obj => obj.Position);
SwapProperties(a1, a2, obj => obj.Name);
Console.WriteLine(a1.Position);
Console.WriteLine(a2.Position);
Console.WriteLine(a1.Name);
Console.WriteLine(a2.Name);
}
I am writing test code to verify a 3rd party API. The API consists of all types of commands, but for this discussion, let's look at a Boolean type of accessor like so:
// The code is simplified to explain the problem.
// Assume "Enable" does complex items like talking
// to a database, or complex calculations.
Blah item = new Blah();
item.GroupA.Enable = true;
item.GroupB.Enable = true;
// etc, say we have A LOT of "groups".
My current unit tests would look something like this:
public void GroupAEnable()
{
bool val = true;
mItem.GroupA.Enable = val;
bool ret = mItem.GroupA.Enable;
VerifyEqual(val, ret);
val = false;
item.GroupA.Enable = val;
ret = mItem.GroupA.Enable;
VerifyEqual(val, ret);
}
public void GroupBEnable()
{
bool val = true;
mItem.GroupB.Enable = val;
bool ret = mItem.GroupB.Enable;
VerifyEqual(val, ret);
val = false;
mItem.GroupB.Enable = val;
ret = mItem.GroupB.Enable;
VerifyEqual(val, ret);
}
I have to repeat this for hundreds of "groups".
In C++, we probably could have macro'd it and do something like this:
#define TEST_BOOL(cmd) \
bool val = true; \
mItem.##cmd## = val; \
bool ret = mItem.##cmd##; \
VerifyEqual(val, ret); \
val = false; \
mItem.##cmd## = val; \
ret = mItem.##cmd##; \
VerifyEqual(val, ret)
public void GroupAEnable()
{
TEST_BOOL(GroupA.Enable);
}
public void GroupBEnable()
{
TEST_BOOL(GroupB.Enable);
}
One C# solution is to create a TestBool function that accepts an Action, but that still requires a lot of typing for each group.
public void TestBool(Action setter, Action getter)
{
...
}
public void GroupAEnable()
{
TestBool(x => mItem.GroupA.Enable = x,
() => mItem.GroupA.Enable);
}
Any cool way to simplify this? The only thing different is the accessor name and type, while the test (i.e. test method) is the same.
Try using reflection to find and invoke the properties you're looking for.
Here's a quick and dirty sample that roughly does what you're trying to do:
public static class Program
{
[STAThread]
static void Main()
{
NeedsTesting target = new NeedsTesting();
DoTest( target );
}
private static void DoTest(NeedsTesting target)
{
Type type = typeof( NeedsTesting );
PropertyInfo[] properties;
int count = 0;
properties = type.GetProperties();
foreach( PropertyInfo property in properties )
{
if( property.Name.StartsWith( "Group" ) )
{
count++;
TestProperty( target, property );
}
}
if( count != 5 )
{
VerifyEquals( false, true, "Did not find all 5 properties to test" );
}
}
private static void TestProperty( NeedsTesting target, PropertyInfo property )
{
bool result;
property.SetValue( target, true );
result = (bool)property.GetValue( target );
VerifyEquals( result, true, string.Format("Property '{0}' failed to retain a 'true' value.", property.Name ) );
property.SetValue( target, false );
result = (bool)property.GetValue( target );
VerifyEquals( result, false, string.Format( "Property '{0}' failed to retain a 'false' value.", property.Name ) );
}
private static void VerifyEquals( bool left, bool right, string message )
{
if( left != right )
{
throw new Exception(
string.Format(
"Unit test failed - values were not equal:\r\n" +
" left: {0}\r\n" +
" right: {1}\r\n" +
"Message:\r\n" +
"{2}",
left,
right,
message
)
);
}
}
}
public class NeedsTesting
{
private bool groupEValue;
public bool GroupA { get; set; }
public bool GroupB { get; set; }
public bool GroupC { get; set; }
public bool GroupD { get; set; }
public bool GroupE
{
get
{
return this.groupEValue;
}
set
{
// Oops, this one is broken.
value = false;
}
}
}
Functions. Sometype may need to become a generic depending on your requirements:
void BoringTest(Sometype item)
{
bool val = true;
item.Enable = val;
bool ret = item.Enable;
VerifyEqual(val, ret);
val = false;
item.Enable = val;
ret =item.Enable;
VerifyEqual(val, ret);
}
public void GroupAEnable()
{
BoringTest(mItem.GroupA);
}
public void GroupBEnable()
{
BoringTest(mItem.GroupB);
}
Another option is to use reflection, if you don't bother about speed. Related: C# - Set Property of a Property with Reflection
dynamic uses reflection and may help you here but I'm not entirely sure. It has been a long time since I used it. Be aware that dynamic fails at runtime instead of compile time.
void BoringTest(object i)
{
dynamic item = i;
bool val = true;
item.Enable = val;
bool ret = item.Enable;
VerifyEqual(val, ret);
val = false;
item.Enable = val;
ret =item.Enable;
VerifyEqual(val, ret);
}
public void GroupAEnable()
{
BoringTest(mItem.GroupA);
}
public void GroupBEnable()
{
BoringTest(mItem.GroupB);
}
A third option is to use an intermediary, such as xml and xslt, or whatever your company fancies, for generation of entire test files.
Here is an expression based approach:
public static void VerifyMemberEqualsValueAfterSetting<TValue>(
Expression<Func<TValue>> memberExpression,
TValue value)
{
var member = (MemberExpression) memberExpression.Body;
var parameter = Expression.Parameter(typeof (TValue));
var assignExpresison = Expression.Assign(member, parameter);
Expression.Lambda<Action<TValue>>(assignExpresison, parameter).Compile()(value);
var after = Expression.Lambda<Func<TValue>>(member, null).Compile()();
VerifyEqual(value,after);
}
Then use it like this:
VerifyMemberEqualsValueAfterSetting(()=> mItem.GroupA.Enabled, true);
VerifyMemberEqualsValueAfterSetting(()=> mItem.GroupA.Enabled, false);
Or even more boiled down:
public static void VerifyMemberEqualsValueAfterSetting<TValue>(
Expression<Func<TValue>> memberExpression,
params TValue[] values)
{
var member = (MemberExpression) memberExpression.Body;
var parameter = Expression.Parameter(typeof (TValue));
var assignExpresison = Expression.Assign(member, parameter);
var setter =Expression.Lambda<Action<TValue>>(assignExpresison, parameter).Compile();
var getter = Expression.Lambda<Func<TValue>>(member, null).Compile();
foreach(var value in values)
{
setter(value);
VerifyEqual(value,getter(value));
}
}
Then its possible to only write
VerifyMemberEqualsValueAfterSetting(()=> mItem.GroupA.Enabled, true, false);
VerifyMemberEqualsValueAfterSetting(()=> whatEver.Count, 1, 2, 3);
I have been playing around with LINQ to Z3 for fun (not production use).
I've ended up with this syntax as a start:
var i = 123;
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
let g = TheormProver.Func<bool, int>()
where !f(a * 2) && g(f(g(f(4)))) == i * a && a < g(f(a))
select new { f = f.ToString(), g = g.ToString(), a, asd = "Test extra property" };
var solution = test2.Solve(); // Edited in for clarification
// note that test2 is a TheormProver<T> which has a "T Solve()" method defined.
The static TheromProver.Int and TheormProver.Func methods/properties simply return a basic type (as per their name) currently.
Moving forwards I want to make a sort of Variable<T> type that contains more information than just a value.
TL;DR: The problem I'm having is that I want f and g variables to be a custom type that I can add fields and properties to, but I still want to be able to use them with the syntax I've got in the where clause (i.e. as a method/Func).
So, How do I create a custom type that can be used in method syntax while adding/having my own properties?
Note that I don't care if calling the method does nothing, or doesn't work as I'll be manipulating the where clause so they'll never get invoked/executed.
Example:
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
where !f(a * 2) && a > 3 // f is used to create a method call expression
select new { f , a };
var testSolution = test2.Solve();
var fSolution = testSolution.f; // F is its own type with unique properties/fields.
var fConstraints = fSolution.Constraints;
var fSomeProperty = fSolution.SomeProperty;
foreach(var constraint in fConstraints)
{
//.....
}
I've mocked up a quick example of the work in progress syntax I have so far:
http://liveworkspace.org/code/3Fm6JM$0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
namespace ConsoleApplication1
{
class TheormProver
{
public static int Int { get { return default(int); } } // Really this would return my Variable<int>
public static Func<T, TResult> Func<T, TResult>() { return default(Func<T, TResult>); } // Really this would return my Variable<Func<T, TResult>>
protected List<Expression> Constraints; // Holds constraints / where clauses that get translated into the Z3 language
//This gets called when we do the first "let" and gets us into the correctly typed world with a generic parameter
public virtual TheormProver<T> Select<T>(Func<TheormProver, T> sel)
{
return new TheormProver<T>(Constraints);
}
}
// This is what the user of the library sees and is returned by a from t in new TheormProver(). T will be the anonymous type from the last let
class TheormProver<T> : TheormProver
{
public TheormProver(List<Expression> Constraints)
{
}
// This gets called on subsequent "let"s, going from the anonymous type with one property "f" to one with 2, "f, g". Chaining this way allows as many lets as we want
public virtual TheormProver<U> Select<U>(Expression<Func<T, U>> sel)
{
return new TheormProver<T, U>(sel, Constraints.ToList());
}
public virtual TheormProver<T> Where(Expression<Func<T, bool>> constraint)
{
var result = (TheormProver<T>)this; // This should be a clone to allow composable queries
result.Constraints.Add(constraint);
return result;
}
public virtual T Solve(out bool foundSolution)
{
// TODO: Call Z3 and get a solution
foundSolution = false;
return default(T);
}
}
internal class TheormProver<T, U> : TheormProver<U>
{
private LambdaExpression Selector;
private TheormProver<T> InternalTheorumProver;
public TheormProver(Expression<Func<T, U>> selector, List<Expression> constraints)
: base(constraints)
{
Selector = selector;
InternalTheorumProver = new TheormProver<T>(constraints);
}
}
class Program
{
static void Main(string[] args)
{
var test = from t in new TheormProver()
let f = TheormProver.Func<int, bool>()
let g = TheormProver.Func<bool, int>()
let a = TheormProver.Int
where g(f(a)) == 0
select new { f, g, a };
bool foundSolution;
var testSolution = test.Solve(out foundSolution);
}
}
}
I've created a simple 'testbed' for your original code: http://liveworkspace.org/code/3Bl7wC$0.
With, a bit of dynamic magic, you can have the following class as a drop-in replacement for Func<T1, T2>:
public class MyCallable<T1, T2> : DynamicObject
{
private readonly Expression<Func<T1, T2> > _wrapped;
private readonly Func<T1, T2> _compiled;
public MyCallable(Expression<Func<T1, T2>> towrap)
{
_wrapped = towrap; _compiled = _wrapped.Compile();
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
if ( (args.Length == 1) &&
(args[0].GetType() == typeof(T1)))
{
Console.WriteLine(#"Invoking ""{0}"" on {1}", _wrapped, args[0]);
result = _compiled((T1) args[0]);
return true;
}
else
{
//throw new ArgumentException("Cannot invoke " + _wrapped + " with the arguments passed");
result = null;
return false;
}
}
}
As you can see, it defines you class as being "dynamic" and allows you to try and invoke it as if it were a delegate/function/... a general callable:
// in "TheormProver"
public static dynamic Func<T1, T2>() { return new MyCallable<T1, T2>(arg1 => default(T2)); }
Here's proof it works: http://liveworkspace.org/code/4kBypd$0
Output:
Invoking "arg1 => False" on 0
Invoking "arg1 => False" on 4
Invoking "arg1 => 0" on False
Invoking "arg1 => False" on 0
Invoking "arg1 => 0" on False
Invoking "arg1 => False" on 0
Invoking "arg1 => 0" on False
Full code for reference:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Dynamic;
public class Program
{
public class MyCallable<T1, T2> : DynamicObject
{
private readonly Expression<Func<T1, T2> > _wrapped;
private readonly Func<T1, T2> _compiled;
public MyCallable(Expression<Func<T1, T2>> towrap)
{
_wrapped = towrap; _compiled = _wrapped.Compile();
}
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
if ( (args.Length == 1) &&
(args[0].GetType() == typeof(T1)))
{
Console.WriteLine(#"Invoking ""{0}"" on {1}", _wrapped, args[0]);
result = _compiled((T1) args[0]);
return true;
}
else
{
//throw new ArgumentException("Cannot invoke " + _wrapped + " with the arguments passed");
result = null;
return false;
}
}
}
public static class TheormProver
{
public static object[] NewTheorm() { return new object[] { 1 }; }
public static dynamic Func<T1, T2>() { return new MyCallable<T1, T2>(arg1 => default(T2)); }
public static int Int { get; set; }
}
public static void Main(string[] args)
{
var i = 123;
var test2 = from t in TheormProver.NewTheorm()
let f = TheormProver.Func<int, bool>()
let a = TheormProver.Int
let g = TheormProver.Func<bool, int>()
where !f(a * 2) && g(f(g(f(4)))) == i * a && a < g(f(a))
select new { f = f.ToString(), g = g.ToString(), a, asd = "Test extra property" };
test2.ToList().ForEach(Console.WriteLine);
}
}
You can't add custom members to delegate types and you cannot overload operator () in C#. That leaves you with extension methods.
Now, you don't want to add extensions to very general delegate types like Func<int, int> because that pollutes the namespace. I suggest you create custom delegates like this:
delegate TResult Z3Func<T1, TResult>(T1 arg1);
Then you can add extensions to Z3Func.
The extension calls will end up as static method calls in the expression tree you are analyzing.
Let's say I have the following class.
MyClass<T>
{
public void MyMethod(T a, List<T> b, List<Tuple<T, string>> c) {}
}
I can get the type of the arguments of the method as follow
Type testType = typeof(MyClass<>);
MethodInfo myMethodInfo = testType.GetMethod("MyMethod");
Type[] paramTypes = myMethodInfo.GetParameters().Select(pi => pi.ParameterType);
How can I manually create an array containing the same open types as paramTypes from a string? For ex from
var typesAsStr = new string[] {"T", "List`1[T]", "List`1[Tuple`2[T, string]]"};
If I had MyClass<int>, I could do something like Type.GetType(fullQualifiedNameOfArg) for each argument, but here I want to keep the generic argument T:
I can't create "a": I can't do Type.GetType("T")
I can almost create "b": I can do Type.GetType("List `1"), but the info on "T" is not yet present
I don't know how to create "c"
I ended up needing this when converting a Mono.Cecil type into a .net type: Cecil gives me the info on a method named "MyMethod" with arguments "T", "List<T>" and "List<Tuple<T, string>>". I then want to get that method using reflection (if there are several methods with the same name and argument numbers, I have to check the args to know which one it is), that's why I'd want to have a way to transform what Cecil tells me into what .Net knows, to be able to compare with what's in paramTypes.
I've also seen several other people asking how to convert a Mono.Cecil type into a .Net one, so that's also why I thought I'd try.
You can get T using strings, you do it by calling GetType with the string name of MyClass and then getting the generic arguments of the resulting type. From there you can build up the other open generic types using MakeGenericType. You have to work from the inside out by constructing the most nested types first. To do it automatically across differing methods would require some string parsing to get to the nested types. For the sake of comparing .Net methods against Cecil methods, #Tengiz might have a better approach.
To run the code, update the string name of MyClass to have the correct namespace for your environment.
private static void Main(string[] args) {
// change 'yournamespace'
Type testType = Type.GetType("yournamespace.MyClass`1");
Type[] testTypeGenericArgs = testType.GetGenericArguments();
// Get T type from MyClass generic args
Type tType = testTypeGenericArgs[0];
Type genericListType = Type.GetType("System.Collections.Generic.List`1");
// create type List<T>
Type openListType = genericListType.MakeGenericType(testTypeGenericArgs[0]);
Type genericTuple = Type.GetType("System.Tuple`2");
Type stringType = Type.GetType("System.String");
// create type Tuple<T, string>
Type openTuple = genericTuple.MakeGenericType(new[] { tType, stringType });
// create type List<Tuple<T, string>>
Type openListOfTuple = genericListType.MakeGenericType(openTuple);
Type[] typesFromStrings = new[] { tType, openListType, openListOfTuple };
// get method parameters per example
Type myClassType = typeof(MyClass<>);
MethodInfo myMethodInfo = myClassType.GetMethod("MyMethod");
Type[] paramTypes = myMethodInfo.GetParameters().Select(pi => pi.ParameterType).ToArray();
// compare type created from strings against types
// retrieved by reflection
for (int i = 0; i < typesFromStrings.Length; i++) {
Console.WriteLine(typesFromStrings[i].Equals(paramTypes[i]));
}
Console.ReadLine();
}
I found this so interesting, that I had to create something myself, and present it to the world... and after a couple hours of exploration, here is what I got...
The extension method for Type: GetMethodByString
This is very simple: get a type and then call the method passing a string that represents the method you want:
var type = typeof(MyType<>);
type.GetMethodByString("MyMethod(T, List`1[T], List`1[Tuple`2[T, String]])")
Sample program
class Program
{
public static void Main()
{
var t1 = typeof(MyType<>);
var mi11 = t1.GetMethodByString("MyMethod(T, List`1[T], List`1[Tuple`2[T, String]])");
var mi12 = t1.GetMethodByString("Method[X](X, T)");
var mi13 = t1.GetMethodByString("Method(List`1[T], Int32 ByRef)");
var t2 = typeof(MyType);
var mi21 = t2.GetMethodByString("Method[X, T](List`1[X], Tuple`2[X, List`1[T]])");
}
class MyType<T>
{
public void MyMethod(T a, List<T> b, List<Tuple<T, string>> c) { }
public void Method(List<T> t, out int i) { i = 0; }
public void Method<X>(X x, T t) { }
}
class MyType
{
public int Method<X, T>(List<X> x, Tuple<X, List<T>> tuple)
{
return 1;
}
}
}
TypeExtensions
public static class TypeExtensions
{
public static MethodInfo GetMethodByString(
this Type type, string methodString)
{
return type.GetMethods()
.Where(mi => MethodToString(mi) == methodString)
.SingleOrDefault();
}
public static string MethodToString(MethodInfo mi)
{
var b = new StringBuilder();
b.Append(mi.Name);
if (mi.IsGenericMethodDefinition)
b.AppendFormat("[{0}]",
string.Join(", ", mi.GetGenericArguments()
.Select(TypeToString)));
b.AppendFormat("({0})", string.Join(", ", mi.GetParameters()
.Select(ParamToString)));
return b.ToString();
}
public static string TypeToString(Type t)
{
var b = new StringBuilder();
b.AppendFormat("{0}", t.Name);
if (t.IsGenericType)
b.AppendFormat("[{0}]",
string.Join(", ", t.GetGenericArguments()
.Select(TypeToString)));
return b.ToString();
}
public static string ParamToString(ParameterInfo pi)
{
return TypeToString(pi.ParameterType).Replace("&", " ByRef");
}
}
Why I didn't try to get types by name
Unfortunately, I found no way to get a type given a string, unless you guess a lot about the type being represented... so, it is quite impossible.
That explains why I did a method to find the method instead. It is much more precise... but it could eventually fail, in very rare and bizarre circumstances:
if you create a List of your own, and then two overloads of the same method, one taking the .Net List and the other taking the List you have created... then it fails
Why not parsing the input string
I found that for the purpose of looking up a method, it is enough to have a fixed syntax string, so that I can generate it from the method and compare... that have some limitations:
must use the name of the type, so C# alliases won't work (string must be named "String", int must be named "Int32" not "int")
EDIT
Performance
This solution is not very performatic, but nothing that a cache cannot solve. The method could use a dictionary, using both the Type and the string as a composite key, and look in there before trying to find the method by bulding a lot of strings and comparing all of them.
If you need thread safety on the cache dictionary, use a ConcurrentDictionary<TKey, TValue>... very nice class.
EDIT 2: Created a cached version
static ConcurrentDictionary<Type, Dictionary<string, MethodInfo>> cacheOfGetMethodByString
= new ConcurrentDictionary<Type, Dictionary<string, MethodInfo>>();
public static MethodInfo GetMethodByString(
this Type type, string methodString)
{
var typeData = cacheOfGetMethodByString
.GetOrAdd(type, CreateTypeData);
MethodInfo mi;
typeData.TryGetValue(methodString, out mi);
return mi;
}
public static Dictionary<string, MethodInfo> CreateTypeData(Type type)
{
var dic = new Dictionary<string, MethodInfo>();
foreach (var eachMi in type.GetMethods())
dic.Add(MethodToString(eachMi), eachMi);
return dic;
}
Hoppe this helps! =)
I don't think .NET allows you to create a type "T" where T is a type argument, which is yet to be specified. So, the array of Type(s) from input string array cannot be created.
However, in the second part of your question, I read that you want to identify the method which has those types given as string. That task is solvable by iterating though the arguments, creating another array of strings describing the method arguments, and then comparing the resulting and input arrays, as follows:
class MyClass<T>
{
public void MyMethod(T a, List<T> b, List<Tuple<T, string>> c) { }
}
class Program
{
static void Main(string[] args)
{
//input.
var typesAsStr = new string[] { "T", "List`1[T]", "List`1[Tuple`2[T, string]]" };
//type to find a method.
Type testType = typeof(MyClass<>);
//possibly iterate through methods instead?
MethodInfo myMethodInfo = testType.GetMethod("MyMethod");
//get array of strings describing MyMethod's arguments.
string[] paramTypes = myMethodInfo.GetParameters().Select(pi => TypeToString(pi.ParameterType)).ToArray();
//compare arrays of strings (can be improved).
var index = -1;
Console.WriteLine("Method found: {0}", typesAsStr.All(str => { index++; return index < paramTypes.Length && str == paramTypes[index]; }));
Console.ReadLine();
}
private static CSharpCodeProvider compiler = new CSharpCodeProvider();
private static string TypeToString(Type type)
{
if (type.IsGenericType) {
return type.Name + "[" + string.Join(", ", type.GetGenericArguments().Select(ga => TypeToString(ga))) + "]";
}
else if (type.IsGenericParameter) {
return type.Name;
}
//next line gives "string" (lower case for System.String).
//additional type name translations can be applied if output is not what we neeed.
return compiler.GetTypeOutput(new CodeTypeReference(type));
}
}
In the [console] output I see that your input string matches the function.
BTW, a lot of optimizations can be applied to this code if you face the performance problems, such as efficient way of working with strings, releasing CSharpCodeProvider instance maybe, etc. But the code is enough to solve the given task as questioned.
You cannot do what you are trying to do, but there is a relatively easy way of achieving the same result by entering from a different direction
Strings do not identify types uniquely
This is the basic problem with converting strings to types: when you see a T, you have no idea where it came from. The following is a valid class definition:
class Simple<T> {
public T Make(T blah) {
return blah;
}
public T Make<T>(T blah) {
return blah;
}
}
Two overloads of Make have parameters that look identical, yet they do not compare as equal. Moreover, there is absolutely no way of getting the T of the generic Make<T> without first getting the MethodInfo for the generic Make<T> - a circular dependency.
What can you do?
Instead of going for the impossible string->Type conversion, you can build a matcher that tells you if an instance of a type, including an unbounded generic type, matches a given string representation:
static bool MatchType(string str, Type type)
With this method in hand, you can walk through all available methods with a particular name, and check the types of their parameter lists one by one against the strings in your array of strings:
var typesAsStr = new [] {"T", "List`1[T]", "List`1[Tuple`2[T, string]]"};
var myMethod = typeof (Simple<>)
.GetMethods()
.SingleOrDefault(m => m.Name == "MyMethod" &&
typesAsStr
.Zip(m.GetParameters(), (s, t) => new {s, t})
.All(p => MatchType(p.s, p.t.ParameterType))
);
How do you implement the MatchType method?
You can use a technique similar to Recursive Descent Parsing: tokenize your string, and then match elements of your type as you go through the chain of tokens. When a class is parameterized, get generic parameters and match them recursively. You need to pay attention to array types, but that is relatively simple as well. Take a look:
public static bool MatchType(string str, Type type) {
var queue = new Queue<Token>(Tokenize(str));
return MatchRecursive(queue, type) && (queue.Count == 0);
}
private static bool MatchRecursive(Queue<Token> tokens, Type type) {
string baseName;
if (!ReadToken(tokens, TokenType.Identifier, out baseName)) return false;
var ranks = new List<int>();
while (type.IsArray) {
ranks.Add(type.GetArrayRank());
type = type.GetElementType();
}
if (type.IsGenericType) {
if (!type.Name.StartsWith(baseName+"`") || !DropToken(tokens, TokenType.Tick)) return false;
string numStr;
int num;
if (!ReadToken(tokens, TokenType.Number, out numStr)
|| !int.TryParse(numStr, out num)
|| !DropToken(tokens, TokenType.OpenBraket)) return false;
var genParams = type.GetGenericArguments();
if (genParams.Length != num) return false;
for (var i = 0 ; i < num ; i++) {
if (i != 0 && !DropToken(tokens, TokenType.Comma)) return false;
if (!MatchRecursive(tokens, genParams[i])) return false;
}
if (!DropToken(tokens, TokenType.CloseBraket)) return false;
}
foreach (var rank in ranks) {
if (!DropToken(tokens, TokenType.OpenBraket)) return false;
for (var i = 0 ; i != rank-1 ; i++) {
if (!DropToken(tokens, TokenType.Comma)) return false;
}
if (!DropToken(tokens, TokenType.CloseBraket)) return false;
}
return type.IsGenericType || Aliases.Contains(new Tuple<string, Type>(baseName, type)) || type.Name == baseName;
}
private static readonly ISet<Tuple<string,Type>> Aliases = new HashSet<Tuple<string, Type>> {
new Tuple<string, Type>("bool", typeof(bool)),
new Tuple<string, Type>("byte", typeof(byte)),
new Tuple<string, Type>("sbyte", typeof(sbyte)),
new Tuple<string, Type>("char", typeof(char)),
new Tuple<string, Type>("string", typeof(string)),
new Tuple<string, Type>("short", typeof(short)),
new Tuple<string, Type>("ushort", typeof(ushort)),
new Tuple<string, Type>("int", typeof(int)),
new Tuple<string, Type>("uint", typeof(uint)),
new Tuple<string, Type>("long", typeof(long)),
new Tuple<string, Type>("ulong", typeof(ulong)),
new Tuple<string, Type>("float", typeof(float)),
new Tuple<string, Type>("double", typeof(double)),
new Tuple<string, Type>("decimal", typeof(decimal)),
new Tuple<string, Type>("void", typeof(void)),
new Tuple<string, Type>("object", typeof(object))
};
private enum TokenType {
OpenBraket,
CloseBraket,
Comma,
Tick,
Identifier,
Number
}
private class Token {
public TokenType Type { get; private set; }
public string Text { get; private set; }
public Token(TokenType type, string text) {
Type = type;
Text = text;
}
public override string ToString() {
return string.Format("{0}:{1}", Enum.GetName(typeof(TokenType), Type), Text);
}
}
private static bool DropToken(Queue<Token> tokens, TokenType expected) {
return (tokens.Count != 0) && (tokens.Dequeue().Type == expected);
}
private static bool ReadToken(Queue<Token> tokens, TokenType expected, out string text) {
var res = (tokens.Count != 0) && (tokens.Peek().Type == expected);
text = res ? tokens.Dequeue().Text : null;
return res;
}
private static IEnumerable<Token> Tokenize(IEnumerable<char> str) {
var res = new List<Token>();
var text = new StringBuilder();
foreach (var c in str) {
var pos = "[],`".IndexOf(c);
if ((pos != -1 || char.IsWhiteSpace(c)) && text.Length != 0) {
res.Add(new Token(
char.IsDigit(text[0]) ? TokenType.Number : TokenType.Identifier
, text.ToString())
);
text.Clear();
}
if (pos != -1) {
res.Add(new Token((TokenType)pos, c.ToString(CultureInfo.InvariantCulture)));
} else if (!char.IsWhiteSpace(c)) {
text.Append(c);
}
}
if (text.Length != 0) {
res.Add(new Token(
char.IsDigit(text[0]) ? TokenType.Number : TokenType.Identifier
, text.ToString())
);
}
return res;
}
It is not quite clear to me what the exactly you need, but i believe you can use the following technique:
object[] parameters = CreateParameters(typeof(MyClass<>), "MyMethod", typeof(int));
Debug.Assert(parameters[0] is int);
Debug.Assert(parameters[1] is List<int>);
Debug.Assert(parameters[2] is List<Tuple<int, string>>);
//...
object[] CreateParameters(Type type, string methodName, Type genericArgument) {
object[] parameters = null;
MethodInfo mInfo = type.GetMethod(methodName);
if(mInfo != null) {
var pInfos = mInfo.GetParameters();
parameters = new object[pInfos.Length];
for(int i = 0; i < pInfos.Length; i++) {
Type pType = pInfos[i].ParameterType;
if(pType.IsGenericParameter)
parameters[i] = Activator.CreateInstance(genericArgument);
if(pType.IsGenericType) {
var arguments = ResolveGenericArguments(pType, genericArgument);
Type definition = pType.GetGenericTypeDefinition();
Type actualizedType = definition.MakeGenericType(arguments);
parameters[i] = Activator.CreateInstance(actualizedType);
}
}
}
return parameters;
}
Type[] ResolveGenericArguments(Type genericType, Type genericArgument) {
Type[] arguments = genericType.GetGenericArguments();
for(int i = 0; i < arguments.Length; i++) {
if(arguments[i].IsGenericParameter)
arguments[i] = genericArgument;
if(arguments[i].IsGenericType) {
var nestedArguments = ResolveGenericArguments(arguments[i], genericArgument);
Type nestedDefinition = arguments[i].GetGenericTypeDefinition();
arguments[i] = nestedDefinition.MakeGenericType(nestedArguments);
}
}
return arguments;
}
Mostly it comes handy that C# delegates already store the object together with the member function. But is there a way, to store -- and pass as parameters -- only the member function itself, just as the good old pointer-to-member-function in C++?
In case the description is less than clear, I give a self-contained example. And, yes, in the example the insistence to pass around member functions is totally pointless, but I have more serious uses for this.
class Foo {
public int i { get; set; }
/* Can this be done?
public static int Apply (Foo obj, ???? method, int j) {
return obj.method (j);
}
*/
public static int ApplyHack (Foo obj, Func<int, int> method, int j) {
return (int) method.Method.Invoke (obj, new object [] { j });
}
public static readonly Foo _ = new Foo (); // dummy object for ApplyHack
public int Multiply (int j) {
return i * j;
}
public int Add (int j) {
return i + j;
}
}
class Program {
static void Main (string [] args) {
var foo = new Foo { i = 7 };
Console.Write ("{0}\n", Foo.ApplyHack (foo, Foo._.Multiply, 5));
Console.Write ("{0}\n", Foo.ApplyHack (foo, Foo._.Add, 5));
Console.ReadKey ();
}
}
You see, the only workaround I've found is rather ugly and probably slow.
What you want is something called an open instance delegate. I've written about them on my blog
Basically, you can create a delegate to an instance method without tying it to a particular instance, and specify the instance to use it on when you call it:
class Foo {
public int i { get; set; }
public int Multiply (int j) {
return i * j;
}
public int Add (int j) {
return i + j;
}
}
class Program {
static void Main (string [] args) {
Func<Foo, int, int> multiply = (Func<Foo, int, int>)Delegate.CreateDelegate(typeof(Func<Foo, int, int>), null, typeof(Foo).GetMethod("Multiply");
Func<Foo, int, int> add = (Func<Foo, int, int>)Delegate.CreateDelegate(typeof(Func<Foo, int, int>), null, typeof(Foo).GetMethod("Add");
var foo1 = new Foo { i = 7 };
var foo2 = new Foo { i = 8 };
Console.Write ("{0}\n", multiply(foo1, 5));
Console.Write ("{0}\n", add(foo1, 5));
Console.Write ("{0}\n", multiply(foo2, 5));
Console.Write ("{0}\n", add(foo2, 5));
Console.ReadKey ();
}
}
Taking your existing code:
public static int ApplyHack (Foo obj, Func<int, int> method, int j) {
return (int) method.Method.Invoke (obj, new object [] { j });
}
You could do something like this:
public static int ApplyHack (Foo obj, Func<int, int> method, int j) {
var func = (Func<int,int>)Delegate.CreateDelegate(typeof(Func<int,int>), obj, method.Method);
return func(j);
}
This will create a new delegate around the method and the new object. To take your first example:
public static int Apply (Foo obj, ???? method, int j) {
return obj.method (j);
}
The type you are looking for is System.Reflection.MethodInfo and it would look like this:
public static int Apply (Foo obj, MethodInfo method, int j) {
var func = (Func<int,int>)Delegate.CreateDelegate(typeof(Func<int,int>), obj, method);
return func(i);
}
Note that while you are allocating delegates for each invocation, I believe this will still be faster than using reflection, since you do not have to box function input/output, nor store it in object[] arrays.
Assuming you're using C# 2.0 or above, and have access to anonymous delegates, you can do it very simply by wrapping the function in an anonymous delegate at the point of storage:
class Foo
{
public Foo(int v)
{
this.v = v;
}
int v;
public int Multiply(int x)
{
return v * x;
}
public int Add(int x)
{
return v+x;
}
delegate int NewFunctionPointer(Foo, int);
delegate int OldDelegateStyle(int);
static void Example()
{
Foo f = new Foo(2);
Foo f2 = new Foo(3);
// instead of this, which binds an instance
OldDelegateStyle oldMul = f.Multiply;
// You have to use this
NewFunctionPointer mul = delegate(Foo f, int x) { return f.Multiply(x); }
NewFunctionPointer add = delegate(Foo f, int x) { return f.Add(x); }
// But can now do this
mul(f, 4); // = 8
add(f2, 1); // = 3
}
}
If you're okay with passing the this reference as a parameter, why not just use static methods?
class Foo {
public int i;
public static int ApplyHack(Foo foo, Func<Foo, int, int> method, int j) {
return method(foo, j);
}
public static int Multiply(Foo foo, int j) {
return foo.i * j;
}
}
Console.Write("{0}\n", Foo.ApplyHack(foo, Foo.Multiply, 5));
This mainly affects how you construct the Foo object, without changing how you use it. It also doesn't prevent you from having a non-static int Multiply(int) method.
You could retrieve and reuse the MethodInfo for the method or just use the name and extract the method at runtime.
public static int ApplyHack (Foo obj, string methodName, int j)
{
var method = typeof(Foo).GetMethod(methodName);
return (int) method.Invoke (obj, new object [] { j });
}
I'd be very careful that this was actually necessary as it seems like a code smell to me.
You can do it that way
class Foo
{
public int i { get; set; }
public static int Apply(Foo obj, Func<int, int, int> method, int j)
{
return method(j, obj.i);
}
public static int Multiply(int j, int i)
{
return i * j;
}
public static int Add(int j, int i)
{
return i + j;
}
}
static void Main(string[] args)
{
var foo = new Foo { i = 7 };
Console.Write("{0}\n", Foo.Apply(foo, Foo.Multiply, 5));
Console.Write("{0}\n", Foo.Apply(foo, Foo.Add, 5));
Console.ReadKey();
}
I think you can do this easily with this if I understand correctly:
public static int Apply(Func<int, int> method, int j)
{
return (int)method.Method.Invoke(method.Target, new object[] { j });
}
and call it like this:
Console.Write("{0}\n", Foo.Apply(foo.Multiply, 5));