I'm a bit new to the concept of "Action" in C# and delegate in general.
I'm trying to study how to build a custom html component in MVC, and I chose the grid component of MVCContrib to start.
To add columns, typically we do
<%= Html.Grid(Model).Columns(column =>
{
column.For(model => model.Date).Format("{0:d}");
column.For(model => model.DayAmount);
column.For(model => model.LeaveType);
})
%>
and I see the source of Columns like the following
public IGridWithOptions<T> Columns(Action<ColumnBuilder<T>> columnBuilder)
{
var builder = new ColumnBuilder<T>();
columnBuilder(builder);
foreach (var column in builder)
{
if (column.Position == null)
{
_gridModel.Columns.Add(column);
}
else
{
_gridModel.Columns.Insert(column.Position.Value, column);
}
}
return this;
}
What I'm confused of is the Action parameter In this instance, Type is CustomBuilder, so when did the "CustomBuilder" object got instantiated?
I suppose, i can rewrite the calling statement above as
Html.Grid(Model).Columns(delegate(CustomBuilder<T> column)
{
});
or a bit more explicit as
Html.Grid(Model).Columns(new Action<CustomBuilder<T>>(delegate(CustomBuilder<T> column)
{
});
);
So are we saying, when the Action was instantiated with the "new" keyword above, the param "CustomBuilder" was instantiated as well?
Lastly, in the
"public IGridWithOptions<T> Columns(Action<ColumnBuilder<T>> columnBuilder)"
function,
the first two lines are
var builder = new ColumnBuilder<T>();
columnBuilder(builder);
What do they do? Looks like it's instantiating ColumBuilder object and pass it as a parameter to Action method columBuilder. Is this where you instantiate the parameter?
Thank you all.
It's nothing to do with action concept.
The delegates is present in .net from the beginning so you should start with the first step. Should build the wall before the roof.
Delegates
Lambda Expressions
Expression trees
But you should know about generic classes and methods, extension methods...
Got it after read this excellent article.
http://www.codeproject.com/Articles/47887/C-Delegates-Anonymous-Methods-and-Lambda-Expressio
while it's talking about Func, the concept applies to Action, which does not return any results.
Looks like the magic happens here
var builder = new ColumnBuilder();
columnBuilder(builder);
I obviously didn't understand the fact that delegate, is just a pointer to a function (anonymous or not). You still need to supply the parameter when calling it. (Duh!).
All cleared up now.
Thank you.
Related
I'm familiar with constructing and calling generic methods through reflection, but for some reason, constructing a generic delegate through reflection is tying my brain in knots!
Perhaps it's because the delegate in particular is not the most simple. This isn't specifically a MongoDb question, but in my case what I'm trying to do is register a class map as a root class where the type is in a type variable because I've only just found it out (not fed in generically).
Ultimately, the method I need to call looks like this:
BsonClassMap.RegisterClassMap<T>(Action<BsonClassMap<T>> classMapInitializer)
So in cases where the class I'm mapping isn't a root class, I don't need to pass the delegate, so the code is pretty straightforward:
MethodInfo method = typeof(BsonClassMap).GetMethod("RegisterClassMap");
MethodInfo genericMethod = method.MakeGenericMethod(entityType);
genericMethod.Invoke(null, null);
I've checked out questions such as How can I dynamically create an Action<T> at runtime? and I understand what's going on there, but for some reason the nested generic in my case is throwing me off and I can't wrap my head around it.
I am trying to construct and invoke the equivalent of this:
BsonClassMap.RegisterClassMap<T>(cm =>
{
cm.AutoMap();
cm.SetIsRootClass(true);
});
Could someone please explain a bit more about generic delegate creation, particularly where the type in the action has a generic type argument of it's own? An example similar to what I'm trying to do would be great!
You should do exactly what the answer in the linked post did.
First, create a generic method that does the thing:
public static void Perform<T>(BsonClassMap<T> cm) {
cm.AutoMap();
cm.SetIsRootClass(true);
}
Then, get the method info of Perform:
var performMethodInfo = typeof(YourType).GetMethod("Perform").MakeGenericMethod(entityType);
Create a Type representing BsonClassMap<T> and create a Type representing Action out of it:
var typeOfBsonClassMap = typeof(BsonClassMap<>).MakeGenericType(entityType);
var typeOfAction = typeof(Action<>).MakeGenericType(typeOfBsonClassMap);
Now use Delegate.CreateDelegate:
var del = Delegate.CreateDelegate(typeOfAction, performMethodInfo);
And then you can pass it into the method:
genericMethod.Invoke(null, new object[] { del });
UPDATED:
I am trying to write a method to do somes work and before it actually does those works it needs to go through some validations. Those validation varies based on what work it's going to do.
After some thoughts, I still want to use the same patterns with some minor changes.
Now, I want to make the following code works:
SomeClass:
public SomeResponse DoSomething<T>(params Func<T, bool>[] validations)
{
if(validations.All(v=>v(T))
{
some logic..
}
return SomeResponse;
}
Usage:
private Func<SomeRequest, bool> ValidateName = r =>
{return !string.IsNullOrWhiteSpace(r.Name);};
private Func<SomeRequest, bool> ValidatePhone = r =>
{return !string.IsNullOrWhiteSpace(r.Phone);};
var someResponse = SomeClass.DoSomething<SomeRequest>(ValidateName,ValidatePhone);
Again, the code currently doesn't work because it's giving me error on
if(validations.All(v=>v(T))
basically Type parameter is not valid here, and I couldn't find a way to pass in an actual SomeRequest object to the Func.
How should I write the code to loop through all the results return by the list of functions and make sure they are returning true, as well as keeping the flexibility of the Type parameter?
Answer:
Found a way to do that, hope this can be helpful:
Simply modify the method definition to :
SomeClass:
public SomeResponse DoSomething<T>(T request, params Func<T, bool>[] validations)
{
if(validations.All(v=>v(request))
{
some logic..
}
return SomeResponse;
}
Then use it like:
var someResponse = SomeClass.DoSomething<SomeRequest>(someRequest, ValidateName,ValidatePhone);
Please let me know if there is any other solution.
You're almost there!
First note that Validations is an array of Func<Request, bool> - that is, each item in the array is a function which takes a Request as a parameter and returns a bool.
So in order to get the bool out of the Func, you need to apply it to a Request object. In C#, applying a Func to an argument looks just like calling a method. So your LINQ expression will look like this:
validations.All(f => f(request))
This will return true if and only if all of the functions in validations return true (when applied to request).
So your full if block will look like this:
// I'm just guessing what the code to make a Request object will look like
Request request = resource.GetRequest();
if (!validations.All(f => f(request)))
{
throw new Exception("Not all of the validations checked out");
}
You haven't provided enough context for me to tell you where to get a Request object from but I'm sure you can figure it out.
Assuming I'm understanding these types correctly, I would think something like this should work:
if (Validations.All(v => v(resource)))
You don't need to use params here, a simple array will do. You can pass an arbitrary number of Func objects with an array.
public void DoSomething(Resource resource, Func<Request, bool>[] Validations)
Anyway, you can easily use LINQ's All method to check if all elements of an array satisfy a predicate.
if (Validations.All(v => v(resource)))
I would like to make my code convention-based by using Types and keeping things simple, but generics has it's own complexity with it's own learning curve.
I have a bunch of POCOs (Plain Old CLR Objects) in a List that I'd like to iterate through later in the code.
var models = new List<Type>();
models.Add(typeof(Person));
models.Add(typeof(Company));
Would like to cycle through each list item:
models.ForEach(m =>
{
var label = m.FullName;
// var data = JsonConvert.DeserializeObject<List<typeof(m)>>(""); // doesn't work
var data = JsonConvert.DeserializeObject<List<m>>(""); // doesn't work either
...
}
The issue is that the "m" in the Deserialize line isn't working. What would be the best way to pass that through, i.e. making the 'List<m>' a 'List<T>' that we can use?
To use generics, you really need to know the Type (T) at compile time, you don't - you know it at run time. (Caveat: Its possible with reflection, but theres no need to use it when there's an overload as described below)
There is an overload of DeserializeObject which takes a Type rather than use generics. So your code would be
models.ForEach(m =>
{
var label = m.FullName;
var data = JsonConvert.DeserializeObject("",m);
...
}
However, as you've pointed out in comments you actually need a List<T> not a single T. You'll need a little bit of reflection, just to create the right type to pass to the above DeserializeObject call.
var tList = typeof(List<>); // Type of open List
models.ForEach(m =>
{
var label = m.FullName;
var tConvert = = tList.MakeGenericType(m);
var data = JsonConvert.DeserializeObject("",tConvert);
...
}
The answer to your question is above, but the more I look at it the harder it is to see what you can actually do with data. all you'll ever know about data is that it is an object. You cant cast it to anything - you wont know if its a list of Person or a list of Company.
Perhaps this was an overly contrived example you've used for a real-life problem. If not I forsee you're next problem is what to do with data!!
If you don't know the type at compile time you can do this with Reflection. Consider the following code:
models.ForEach(m =>
{
var mi = JsonConvert.GetType()
.GetMethod("DeserializeObject");
var m = mi.MakeGenericMethod(new[] { m });
// you pass [null] for the object because it's a [static] method
// and you don't have to declare [args] if you can express it simply
// but keep in mind that it's simply an object[]
m.Invoke(null, args);
}
Another solution is to call the generic method using reflection (if there isn't any overload that takes the type as parameter)
models.ForEach(m =>
{
MethodInfo method = typeof(JsonConvert).GetMethod("DeserializeObject");
MethodInfo generic = method.MakeGenericMethod(m);
generic.Invoke(null, "");
}
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
This question already has answers here:
Where do I use delegates? [closed]
(8 answers)
Closed 9 years ago.
I've previously asked a question of about Delegates does anyone have a must have scenario where I would have to use a delegate? How does this improve my C# code?
Just as many scenarios I use it in I've always seem to be able to program around it.
Whenever you're using a Strategy Pattern or an Observer Pattern, delegates make your work much easier than using interfaces.
Nobody mentioned this, but if you are using LINQ with Lambda you use anonymous methods all the time. Which are technically still delegates.
Lets say you have a class called Person
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
And you wanted to implement a find method where you would find the person based on their FirstName
public Person Where(List<Person> list, string firstName)
{
//find the string
foreach(Person item in list)
if(item.FirstName.Equals(firstName))
return item;
}
This is a very specific search and not very dynamic, meaning if you wanted to search by LastName you would have to change this method or write a new one.
Luckily LINQ provides an extension method called Where to which you need to pass a delegate, which you can create on the fly with the help of anonymous methods.
for instance
string searchString = "Stan";
list.Where( person => person.FirstName.Equals(searchString));
but if you wanted to change to search by LastName you would simply do this
string searchString = "R";
list.Where( person => person.LastName.Equals(searchString));
This example might be not what you were looking for, but I just wanted to show that sometimes we use delegates all the time without thinking about it or realizing it.
Assuming you're not talking about events - of course you can program around it. The point is to make it nicer and cleaner.
protected void Sort()
{
foreach (string key in _dBase.Keys)
{
Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key],
new Comparison<Pair<string, Dictionary<string, T>>>(
delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
{
if (a == null && b != null)
return 1;
else if (a != null && b == null)
return -1;
else if (a == null && b == null)
return 0;
else
return a.First.CompareTo(b.First);
}));
}
}
Could I do that without an inline delegate? Sure. Would I have a floppy private method in my class that would only be used for this one instance? Yup.
Edit: As mentioned in the comments, you can simplify:
Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key],
new Comparison<Pair<string, Dictionary<string, T>>>(
delegate(Pair<string, Dictionary<string, T>> a, Pair<string, Dictionary<string, T>> b)
{
to
Array.Sort<Pair<string, Dictionary<string, T>>>(_dBase[key], (a,b) =>
{
If you imagine C# without delegates, you would commonly encounter situations where you have classes or interfaces with one method. The name of that method is redundant. e.g.
public interface IGetMail
{
Mail JustGetTheMail();
}
The interface is all about that one method. A reference to an object of that type is really no more than a reference to a single callable method. The calling code:
Mail m = getMail.JustGetTheMail();
could be abreviated to:
Mail m = getMail();
The compiler could do that as "syntactic sugar" without any ambiguity, because there's only one method you could possible call on that getMail reference.
So let's add that feature to our C# compiler. Now, when declaring these types, we could make that a little neater as well. We don't need to specify the method name when calling it, so why should we have to give the method a name in the first place?
Let's pick a standard method name, Invoke, i.e.
public interface IGetMail
{
Mail Invoke();
}
We'll add some more syntactic sugar to allow us to write that as:
public delegate Mail GetMail();
Hey presto. We've added delegates to our C# compiler.
(Technically the CLR is also aware of delegates, and so rather than generating an interface, the C# compiler generates a special "delegate" type, which has support for asynchronous invocation, and manipulating an immutable list of delegates and treating them as a single reference; but in a basic form it could have been done with interfaces. There is a proposal to do that for Java).
We can then go further and add anonymous delegates - making them succinct to implement in a way that interfaces are not.
So to answer your question - any time where your interface has one method, it could be a delegate, and you'll be able to seriously cut down the amount of junk code you have to write.
Real World Usage:
Assume you have a simple user control called Checker- which comprises of just 2 checkboxes - chkA and chkB.
Within the user-control you can control the check/uncheck events by implementing the respective events fro chkA and ChkB
3.Now, in a new Win Form , when you drag in Checker...and your objective is to make sure that when chkA is clicked you have to change the background color of a label...lblColorPicker.
Mind you lblColorPicker is a control that exists in the form and is not directly bound to Checker.
How will you achieve this?
Answer:
First, you have to create a new event for your user control Checker.
To create this new event the first thing would be to create a delegate in you user control and then use this delegate as a defining type for the new event you are writing.
And then this Event has to be mapped to chkA...event in your user control.
This way you can control chkA...through the new event from any new form by referencing the event...through a delegate you just wrote.
So, much for Real-World usage!
This objective CANNOT be achieved with out writing the delegate.
Let me know if you think otherwise...or if you need more elaboration.
Anonymous delegates make the code much more readable in some case (you don't have to go to another method to see code that belongs to your method:
Winforms example
class MyForm:Form{
//...
protected override void OnLoad(EventArg e){
this.Cursor=Cursors.Wait();
this.Enabled=false;
// do a long running DB operation without blocking the UI Thread
ThreadPool.QueueUserWorkItem(state=>{
DoLongDBOperation();
// re enable the form
BeginInvoke(new Action(()=>{ this.Cursor=Cursors.Default;this.Enabled=true;}));
});
}
Delegates are an absolute must-have if you add events to your class or are doing anything asynchroneous (There are several other good reasons to have delegates). Benefits is that it is a very flexible approach.
I think you are referring to defining custom delegates?
EventHandler has minimised the requirement for custom delegate definitions but they are still useful if you want to add additional parameters to the method signature.
Whenever you need to modify or change any properties of a winForms control, you need to use a delegate to pass control back to the thread the control was created on... to name just one of many examples.
One example would be a pub/sub message dispatcher. You would need to register the events with the dispatcher and then call them appropriately. This allows you to connect disparate pieces of your code quite easily. I can't think of a way to do this without using delegates
Say you have a console application that responds to different key presses:
Action a = () => {/* Do Stuff*/};
Action b = () => {/* Do Stuff*/};
Action c = () => {/* Do Stuff*/};
Action d = () => {/* Do Stuff*/};
Action e = () => {/* Do Stuff*/};
Action f = () => {/* Do Stuff*/};
Action g = () => {/* Do Stuff*/};
Action h = () => {/* Do Stuff*/};
Action i = () => {/* Do Stuff*/};
Action j = () => {/* Do Stuff*/};
List<Action> actions = new List<Action>() {a,b,c,d,e,f,g,h,i,j};
string line;
while((line = Console.ReadKey().KeyChar) != 'q')
{
if(line.isBetween_0_and_9())
{
actions[line.ParseInt()]();
}
}
You can obviously just use a bunch of Ifs but this not only easier but it's almost certainly more clear/readable.