I tried to use InvokeSelf for silverlight to communicate with html:
InvokeSelf can take object[] as parameter when making a call:
ScriptObject Myjs;
ScriptObject obj = Myjs.InvokeSelf(new object[] { element }) as ScriptObject;
then I want make a call like with anonymous delegate:
Object obj;
obj = InvokeSelf(new object[] { element, delegate { OnUriLoaded(reference); } });
I got the error said:
Cannot convert anonymous method to type 'object' because it is not a delegate type
How to resolve this problem?
The problem is that you cannot assign an anonymous method to an object. This is because the C# compiler doesn't know what delegate type should be used. You can fix the code by creating a delegate explicitly. Since this is Silverlight you can also use more succinct lambda expression notation:
obj = InvokeSelf(new object[]
{ element, new Action(() => OnUriLoaded(reference)) });
That said, I'm not sure if it is possible to pass a delegate to JavaScript, but you should be able to compile the code now and try that.
Related
Consider the following code:
bool result;
Func<int, bool> lambda1 = i => i == 9000;
MethodInfo lambda1Method = lambda1.Method;
result = (bool)lambda1Method.Invoke(null, new object[] { 9000 }); // this works, result = true
int myLocalVariable = 9000;
Func<int, bool> lambda2 = i => i == myLocalVariable;
MethodInfo lambda2Method = lambda2.Method;
result = (bool)lambda2Method.Invoke(null, new object[] { 9000 }); // error
Invoking lambda2Method results in a System.Reflection.TargetException:
Non-static method requires a target.
This question here explains why the lambda1Method is static, while lambda2Method is non-static. Basically if lambdas contain local variables, a class is dynamically created that interprets each local variable as a field. lambda2Method becomes an instance method of that new class. I know this because lambda2Method.DeclaringType is <>c__DisplayClass1, and lambda2Method.IsStatic is false.
My question is, how can I make this work? I understand that because lambda2Method is non-static, I need to supply a value for the object obj parameter of MethodBase.Invoke(), and it needs to be an instance of <>c__DisplayClass1, but how do I obtain this instance?
The main issue that you need to address in you question is How to create an instance of a type generated by the compiler ?
So, if you really have to use MethodInfo, then you can create the required instance by using Reflection:
var instance = Activator.CreateInstance(lambda2Method.DeclaringType);
result = lambda2Method.Invoke(instance, new object[] { 9000 });
Summary:
The declaring type for your method lambda2 is a hidden class generated by the compiler. MethodInfo.Invoke requires a target instance of that type to invoke a non-static method.
Edit:
To get the captured value of myVariable correct, you can make use of the Target property :
result = lambda2Method.Invoke(lambda2.Target, new object[] { 9000 });
I've specified type in a variable: Type hiddenType. I need to create a Func<T> delegate where T is of type specified in mentioned variable and assign an method:
var funcType = typeof(Func<>).MakeGenericType(hiddenType);
Func<object> funcImplementation = () => GetInstance(hiddenType);
var myFunc= Delegate.CreateDelegate(funcType , valueGenerator.Method);
It doesn't works - because funcImplementation is returns object instead of desired. At runtime, it will surely be an instance of type specified in hiddenType.
GetInstance returns object and signaure cannot be changed.
You can solve this by building an expression tree manually, and inserting a cast to hiddenType. This is allowed when you construct an expression tree.
var typeConst = Expression.Constant(hiddenType);
MethodInfo getInst = ... // <<== Use reflection here to get GetInstance info
var callGetInst = Expression.Call(getInst, typeConst);
var cast = Expression.Convert(callGetInst, hiddenType);
var del = Expression.Lambda(cast).Compile();
Note: the above code assumes that GetInstance is static. If it is not static, change the way you construct callGetInst to pass the object on which the method is invoked.
Instead of using a Type, you could consider using a generic wrapper, if it's not possible for you to change the GetInstance signature:
private Func<THidden> GetTypedInstance<THidden>()
{
return () => (THidden)GetInstance(typeof(THidden));
}
Then you can just call it with
GetTypedInstance<SomeClass>();
instead of
GetInstance(typeof(SomeClass));
The code below is valid:
IEnumerable<SomeThing> things = ...;
// map type SomeThing to a new anonymous type, resulting in a strongly typed
// sequence based on an anon type
var newList = things.Select(item =>
{
return new
{
ID = item.ID,
DateUpdatedOrCreated = ((DateTime)(item.DateUpdated ??
item.DateCreated)).ToShortDateString(),
Total = item.Part1 + item.Part2
};
});
newList now appears in Visual Studio as IEnumerable<'a> and is strongly typed with the anonymous type created in the function. That is so cool.
What I can't seem to do is figure out a way to assign just the lambda expression (and not the enumeration) to an implicitly typed variable. Even though the compiler has no problem with the anonymous type in the context above, if I try (say)
var func = (SomeThing item)=> {
return new { ... };
};
I get the error "Cannot assign lambda expression to implicitly-typed local variable". This seems a strange compiler limitation; unless I am missing something, the types are just as non-ambiguous in the 2nd example as they are in the first first: both type parameters are well defined.
Is there any way to do this? Since it's an anonymous type, of course, I don't have any way to use a type to assign it explicitly, so it seems I'd be stuck with making a class for the output type if not.
Update
Shortly after going about my merry way with Jon Skeet's answer, I found a similar dilemma instantiating classes. In case it's not obvious, the same trick can be used to create strongly typed classes using inferred anonymous types.
class Processor<T,U>
{
public Processor(Func<T,U> func) {
}
}
// func is a delegate with anon return type created using method in answer below
var instance = new Processor(func); // does not compile! Requires type arguments!
cannot be created directly, but can be created in much the same way as the trick below:
public static Processor<T,U> Create<T,U>(Func<T,U> func) {
return new Processor<T,U>(func);
}
var instance = Processor.Create(func); // all good
You can do it via type inference:
var func = BuildFunc((SomeThing item) => {
return new { ... };
});
...
static Func<TSource, TResult> BuildFunc<TSource, TResult>(
Func<TSource, TResult> function) {
return function;
}
Note that BuildFunc doesn't really do anything - it just provides the method call needed to get the compiler to do type inference for the generic type arguments for Func<,> - it adds the information that you're interested in Func<,>, basically - that's information which can't be specified as part of a variable declaration, without also specifying the type arguments.
Can anyone advise why this line of code would not compile? It generates CS1660 instead:
s.run_button.Invoke((b) => { b.Enabled = false; },
new object[] { s.run_button });
Visual studio says: Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
Lambda expressions by themselves have no type and are not convertible to System.Delegate. The Invoke method has the type System.Delegate and hence it won't compile because the lambda expression has no type. You need to provide an explicit type conversion here
s.run_button.Invoke(
(Action<Button>)((b) => { b.Enabled = false; }),
new object[] { s.run_button });
The Invoke method takes a parameter of type Delegate. It was written before lambdas entered our world. The easiest solution for you is to wrap your lambda with an Action. I'm not sure precisely what type "b" is (and neither does the C# compiler, hence the error), so you'll have to pass it in explicitly. Something like:
s.run_button.Invoke(new Action<Button>(b => b.Enabled = false), new object[] { s.run_button });
I was going through Jeffrey Palermo's book and came across this syntax.
private void InitializeRepositories()
{
Func<IVisitorRepository> builder = () => new VisitorRepository();
VisitorRepositoryFactory.RepositoryBuilder = builder;
}
What does it mean?
() => indicates a lambda expression that takes no arguments.
In general, it means a function with no arguments.
In this particular example, it creates an anonymous function with no arguments that returns a new VisitorRepository(); object every time.
Func<IVisitorRepository> stands for a delegate which takes no arguments and returns a IVisitorRepository. The creation of that delegate is a lambda function:
() //means no parameters
=> new VisitorRepository()// means it returns a new VisitorRepository
() is the place where you place your variables
Example a common event handled would look like (sender, args)
=> // means throw these parameter into this method
after => you can either drop a one line execution thing like new VisitorRepositor()
OR
you can place a whole function like
Func<IRepository> = (sender, args) =>
{
var myObject = (SomeObject)sender;
return new VisitorReposiroty { id = myObject.SomeId };
}
As other stated it's lambda expression and it really clears your code from method or function that handle a specific event.
Once you read them good it's really damn useful.
The () => syntax is a lambda expression. Lambdas were introduced in C# 3.0 and are used to define an anonymous method for a delegate.
The delegate is defined using the generic Func. So in this case the signature for the delegate is: no input parameters and one output parameter of type IVisitorRepository.
So on the left side of the => lambda array are the names of the input parameters. In case of no input parameters just write (). On the rightside of the => lambda is the code to return the output parameter, in this example: new VisitorRepository().
I suggest read more about lambda expressions in C# to fully understand this code. There is also a generic delegate involved, so you need understanding of Generics and Delegates as well.
Func is a delegate without parmeter and with an IVisitorRepository return value.
() => is a lambda expression creating an anonymous method.
new VisitorRepository() is the content of this anonymous method.
so this line is creating a delegate which is pointing to a anonymous method, which is returning an instance of VisitorRepository.
Func<IVisitorRepository> builder = () => new VisitorRepository()
In the next line, you set the value of a static property to this just created delegate.
VisitorRepositoryFactory.RepositoryBuilder = builder;
After this you can use the property to call the anonymous method, which is creating a new instance of VisitorRepository.
IVisitorRepository repository = VisitorRepositoryFactory.RepositoryBuilder();
In this case, repository will be an instance of VisitorRepository.
It means a function takes no parameters, like:
delegate() {//}