c# Is it possible to supply a lambda when an interface is required?
Solution 1
Delegates cannot implement interfaces (directly).
Two good options come to mind:
Change the definition of the method that you're calling to take a delegate types instead of an
IProgress
type. (If possible; this would be the preferable option)Create a new type that implements the interface that you need and takes a delegate as a parameter to implement that functionality.
And example of #2, while dependent on the interface, might look something like this:
interface IProgress<T>
{
void doStuff(T param);
}
class LambdaProgress<T> : IProgress<T>
{
Action<T> action;
public LambdaProgress(Action<T> action)
{
this.action = action;
}
public void doStuff(T param)
{
action(param);
}
}
then you'd be able to do something like:
B(new LambdaProgress<Object>(obj => ...));
Solution 2
No, you can't supply a lambda when an interface is required.
But you can supply an anonymous object by using impromptu-interface.
This example is from its project page:
//Anonymous Class
var anon = new
{
Prop1 = "Test",
Prop2 = 42L,
Prop3 = Guid.NewGuid(),
Meth1 = Return<bool>.Arguments<int>(it => it > 5)
}
var myInterface = anon.ActLike<IMyInterface>();
In your example this can be:
A
{
// Create an anonymous object.
var anonymous = new
{
// Define a method that needs an "object" parameter and returns nothing.
Report = Return.Arguments<object>(m =>
{
// Do whatever you want to do when Report is called.
})
}
// Get your anonymous object as an IProgress<Object>.
var obj = anonymous.ActLike<IProgress<Object>>
// Call B.
B(obj);
}
Solution 3
Assuming that your IProgress<object>
interface has just the single void Report(object)
method, and that you control the API, you could simply redefine the methods that currently require a parameter of type IProgress<object>
to instead require a new delegate type:
public delegate void ProgressReportDelegate(object someObject);
Then your example could change to:
method in class A {
...
Action<Object> Report = (m) => { // do something useful with m };
B(Report)
}
method B(ProgressReportDelegate reporter) {
reporter(someObject);
}
For more complex interfaces, or where you don't control the API (and so can't change a method to take the delegate rather than on object implementing that interface), this isn't really an option, but it would appear to work in your case.
Related videos on Youtube
Michael Ray Lovett
Updated on September 15, 2022Comments
-
Michael Ray Lovett over 1 year
In some class method, A, I need to call a library method B, which takes as an
IProgress<Object>
as a parameter.Normally, I might either implement
IProgress<Object>
as part of class where A resides, and then pass "this" to method B. Or perhaps I might create a new class whose only purpose is to implementIProgress<Object>
and handle it correctly-- then in this case I'd create an instance of that class and pass it to B.But what I really want is to have my implementation of
IProgress<Object>
to appear right inside the method in which I'm calling B, so that there's less of a visual disconnect between the calling code, and theIProgress<Object>
implementation. (I consider my implementation of IProgress to be kind of a private, non-shared detail of the calling method and thus I don't want my implementation ofIProgress<Object>
to be in a whole separate method of perhaps a whole other class).What I've been trying to do is use a lambda in which I will define my short progress handling, and then somehow pass this lambda to B, like this:
method in class A { ... Action<Object> Report = (m) => { // do something useful with m }; B(Report) } method B(IProgress<Object> reporter) { reporter.Report(some object) }
Of course, I know why this won't work as is - B is wanting an object that implements
IProgress<Object>
and I'm handing it an Action object instead.Is there any way to achieve what I'm trying to achieve? (IE have my implementation if
IProgress<Object>
appear inside method A?-
Hristo Iliev over 11 yearsC# lambdas are anonymous delegates. What you need is an anonymous type which implements the interface. See this question for some workarounds over the only-public-properties anonymous types that C# provides.
-
-
wensveen over 2 yearsThis answer is correct when the question is actually about
System.IProgress<T>
which isn't explicitly stated, but it is implied. -
Servy over 2 yearsThis question isn't asking about the .NET
IProgress<T>
interface. It was asked before that interface event existed. They're asking about their own custom interface. -
A.T. over 2 yearsThe solution here is to use the new IProgress in combination with the new Progress class rather than rolling your own.
-
Servy over 2 yearsThe problem is how to implement an arbitrary interface using a delegate. That the one example used to demonstrate the problem happened to be called
IProgress
is irrelevant to the question. The question did not ask how to update the UI of a desktop application from a background process with the progress of that background task. You're answering a different question than the one that was asked. Given that their question mentions nothing about marshaling to a UI thread, it's not even clear that your solution is even applicable to the context in which they're reporting progress.