I have a protected method in a base class which accepts a Func<T> and then turns around and executes with some added goodness. Example usage:
public MyResponse DoSomething(MyRequest request)
{
return base.Execute(() => this.Channel.DoSomething(request));
}
What I'm looking to do is take the func delegate instance and redirect the method call in the expression to another instance besides this.Channel, so something like:
protected TResponse Execute<TResponse>(Func<TResponse> command)
{
return command.Method.Invoke(this.otherInstanceOfChannel, command.Target);
}
Here the "this.otherInstanceOfChannel" would be an instance of a different concrete class than the "this.channel" passed in the original call but implements the same interface. I just need to figure out what method is being called and execute that on another instance passing in the original arguments from the caller. I started down the path of MethodCallExpressions and the like but my expression-foo is weak...
Edited/rewrote for clarity - hope this version makes more sense.
Thanks,
Matt
Yes you can do this. No time right now to give you the full solution but here is a skeleton of what you would do:
protected TResponse Execute<TResponse>(Expression<Func<TResponse>> command)
{
// Check that the expression is in the correct format (ie you are calling a method off of a type Channel
// Get the name of the method call. Something like:
var node = expr.Body as MemberExpression;
if (object.ReferenceEquals(null, node))
throw new InvalidOperationException("Expression must be of member access");
var methodName = node.Member.Name;
// Use reflection to invoke methodName on otherInstanceOfChannel
// Cast the results to TResponse and return
}
As you can see the only real trick is the use of Expression<>. The type change is transparent to any client code - they don't have to change at all. Here is some code to get you started with parsing expression trees.
I believe that you can provide the instance in the lambda expression like so:
IMyChannel myChannelInstance = MyChannelInstanceFactory.Create();
Execute(() => myChannelInstance.DoSomething(request))
If this can not be done with lambda expressions and I am sure they can you can change this to a delegate and it would work fine. The lambda expression is pointing to a code execution block and as such you can put whatever matches the expression arguments in that code block.
Related
I am working on PCL which along with a lot of functionality also provides log in. Also I recently started using delegates.
The Current Case:
I have a Simple methods that takes in parameters and provide GPlus, Facebook or Simple logIn with Username and Password. as in the code below:
public async Task<SignInResponse> SignInUsingFacebook(IFacebookInitializer faceBookConfiguration)
{
//my code
}
public async Task<SignInResponse> SignInUserNameAndPass(string username,string password)
{
//my code
}
public async Task<SignInResponse> SignInUsingGPlus(IGPlusInitializer gPlusConfiguration)
{
//my code
}
This is great, I can call them from my application directly and handle data but,
I recently came across Delegates and Func<T,TResult>
What I want to do:
I want a simple method that takes in a parameter an enum of LogInType as below:
public enum LogInType
{
UserNameAndPassword,
Facebook,
GooglePlus,
}
and based on the type of login type provided to the method, handles the LogIn process on it's own and just returns the SignInResponse object.
Is there a way this can be done using Delegates. Rather than having 3 individual methods to call for each case. If yes, then can someone please help in the parameters to be passed to the Single method along with The LogInType. I know it has to be a Func but what would the Func look like as it has to take 3 different parameters.
As From the Comments:
Each of those methods is a different signature anyway so you have a Func<IFacebookInitializer, Task<SignInResponse>>, Func<string, string, Task<SignInResponse>> and Func<IGPlusInitializer, Task<SignInResponse>> so you'd still end up with an if statement.
Can I return a Func when the method is called? this ways I can return either of the three func based on a quick switch case. The issue would be (if it's possible) what would be the generic response (or the common response) type of the method that returns either of these three methods
The generic Func works as follows:
The last datatype that you define in Func - "output" in this case should be the return type of the method which you are going to that particular function and the method should also be static.
This might help:
Func<LogInType, string> Login = LoginMethod;
private static string LoginMethod(LogInType loginType)
{
if (loginType == LogInType.Facebook)
return "Facebook";
if (loginType == LogInType.GooglePlus)
return "GooglePlus";
if (loginType == LogInType.UserNameAndPassword)
return "UserNameAndPassword";
return "Default";
}
The return type in the above example is string just for explaining.
I have three projects
MVC Web application
Service application which is kind of two layers business/repository
Entity framework (all EF configuration lives here)
MVC references > service
Service references > EF
I have these three methods currently that do some work.
public bool StoreUpload<T>(UploadInformation information)
where T : class, IUploadEntity { }
public bool RemoveUpload<T>(UploadInformation information)
where T : class, IUploadEntity { }
public bool CommitUpload<T>(UploadInformation information)
where T : class, IUploadEntity { }
I call these three methods from my controller using these interfaces which delegate to the work methods above:
Boolean StoreUpload(UploadInformation information);
Boolean RemoveUpload(UploadInformation information);
Boolean CommitStoredDocuments(UploadInformation information);
Based on a condition from UploadTypes enumeration in a switch I call the correct work method. I do this because I don't want my mvc project to have access to the EF database types otherwise I know someone is going to start querying data from all over the application. I use these switch statements for all interfaced methods:
public bool StoreUpload(UploadInformation information)
{
switch (information.Type)
{
case UploadTypes.AutoIncident:
return RemoveUpload<AutoIncident>(information);
case UploadTypes.Incident:
return RemoveUpload<IncidentInjury>(information);
case UploadTypes.Inspection:
return RemoveUpload<Inspection>(information);
case UploadTypes.OtherIncident:
return RemoveUpload<OtherIncident>(information);
default:
return false;
}
}
public bool RemoveUpload(UploadInformation information) { ... }
public bool CommitStoredUpload(UploadInformation information) { ... }
This method might shed a little light on what the types parameters are being used for. I am updating tables in a generic way using EF.
private bool CommitStoredDocuments<T>(UploadInformation information) where T : class, IUploadEntity
{
var uploads = GetStoredUploads(information.UniqueId);
var entity = db.Set<T>().Include(e => e.Uploads)
.Single(e => e.UniqueId == information.UniqueId);
entity.Uploads.AddRange(uploads);
...
}
It would be nice to be able to pass the work method which requires a type parameter as a delegate to the switch work method calls.
public bool DoSomeWork(delegateMethod, information) {
switch(information.Type) {
case UploadTypes.AutoInciden:
return delegateMethod<AutoIncident>(information);
...
}
}
Can this be done?
Also, I had trouble constructing a good title for this question so please comment if these is a better way to describe the challenge.
It cannot be done directly due to several reasons.
First of all, as you probably noticed, delegateMethod<FooBar>(information) simply does not compile. This is because in your example the delegateMethod is a local variable (method parameter actually, but still a variable), and you cannot apply "type arguments" <FooBar> to a variable - you can apply them only on an identifier that indicates a (generic) type or a (generic) method.
Second reason is more interesting. When you pass a method as a delegate, the delegate actually catches the whole method signature, including all parameter types.
void Blah<T>(UploadInformation information){ ... }
var one = new Action<int>(Blah); // -> Blah<int>
var two = new Action<float>(Blah); // -> Blah<float>
var thr = new Action<andsoon>(Blah); // -> Blah<andsoon>
MagicDoSomeWork(one, ...); // these all
MagicDoSomeWork(two, ...); // delegates are already bound
MagicDoSomeWork(thr, ...); // and remember their concrete T
You need to actually specify the type for the Action so a proper version of generic method will be picked from a general description called Blah. These delegates are bound to concrete versions of the method and will accept only that types. These delegates are 'closed' in terms of their type arguments. Using normal ways, the MagicDoSomeWork will simply have no way of altering the T which these delegates already have remembered.
That two things are a kind of show stoppers, since by normal code only, you cannot write things like
var nope1 = new Action(Blah); // ctor for Action NEEDS type parameter
since Action constructor simply requires a type parameter. And once you pass any, it will lock the Blah type arguments
Also you cannot use open delegates:
var nope1 = new Action<>(Blah); // can't use empty <> in this context :(
since new operator requires a full type to create an object.
However, with a bit of reflection voodoo, it is possible to analyze and build a generic type or a generic method dynamically.
// first, build the delegate in a normal way
// and pick anything as the type parameters
// we will later replace them
var delegateWithNoType = new Action<object>(Blah);
// delegate has captured the methodinfo,
// but uses a stub type parameter - it's useless to call it
// but it REMEMBERS the method!
// .... pass the delegate around
// later, elsewhere, determine the type you want to use
Type myRealArgument;
switch(..oversomething..)
{
default: throw new NotImplemented("Ooops");
case ...: myRealArgument = typeof(UploadTypes.AutoIncident); break;
...
}
// look at the delegate definition
var minfo = delegateWithNoType.Method;
var target = delegateWithNoType.Target; // probably NULL since you cross layers
var gdef = minfo.GetGenericDefinition();
var newinfo = gdef.MakeGenericMethod( myRealArgument );
// now you have a new MethodInfo object that is bound to Blah method
// using the 'real argument' type as first generic parameter
// By using the new methodinfo and original target, you could now build
// an updated delegate object and use it instead the original "untyped" one
// That would be a NEW delegate object. You can't modify the original one.
// ...but since you want to call the method, why don't use the methodinfo
UploadInformation upinfo = ... ;
newinfo.Invoke(target, new object[] { upinfo });
// -> will call Blah<UploadTypes.AutoInciden>(upinfo)
word of warning: this is a sketch to show you how the delegate.Method/Target and methodinfo and getgenericdefinition and makegenericmethod work. I wrote it from memory, never compiled, never ran. It can contain minor typos, overlooked things and invisible rainbow unicorns. I didn't noticed any. Probably because they were invisible.
You can do it like this
public bool Invoke(EntityType entityType, ActionType action, Object[] arguments)
{
var actionType = Enum.GetName(typeof(ActionType), action);
var type = GetType();
var method = type.GetMethods().Single(m => m.IsGenericMethod && m.Name == actionType);
switch (entityType)
{
case EntityType.IncidentInjury:
var genericMethod = method.MakeGenericMethod(typeof(IncidentInjury));
return (bool)genericMethod.Invoke(this, arguments);
default:
return false;
}
}
The enum will just be a list of methods that I want to invoke this way and I create a base class for my services so I don't have to pass the instance to the Invoke method.
Instead of using delegates, consider using an interface (or abstract class). This way, your methods can retain their generic nature.
For example, if you create an interface like:
interface IUploadAction
{
bool Perform<T>(UploadInformation information)
where T : class, IUploadEntity;
}
Note that the T is not exposed in the type, it's only on the method. This is the key part.
Now you can implement this for your database methods:
class CommitStoredDocuments : IUploadAction
{
public bool Perform<T>(UploadInformation information)
where T : class, IUploadEntity
{
var uploads = GetStoredUploads(information.UniqueId);
var entity = db.Set<T>().Include(e => e.Uploads)
.Single(e => e.UniqueId == information.UniqueId);
entity.Uploads.AddRange(uploads);
//...
}
}
Your switching/dispatching method can look like this:
public bool DoAction(IUploadAction action, UploadInformation information)
{
switch (information.Type)
{
case UploadTypes.AutoIncident:
return action.Perform<AutoIncident>(information);
case UploadTypes.Incident:
return action.Perform<IncidentInjury>(information);
case UploadTypes.Inspection:
return action.Perform<Inspection>(information);
case UploadTypes.OtherIncident:
return action.Perform<OtherIncident>(information);
default:
return false;
}
}
And then you can write something like:
IUploadAction storeUpload;
public bool StoreUpload(UploadInformation information) => DoAction(storeUpload, information);
I have the below code snippet in my project. I am new to lambda expressions. I have some idea about it and also
started using it. But I do not understand how the below code is working. Specially,
NotifyIntrenal( notification, callback, changedTypes => ..
Now here changedTypes is one of the parameter for method NotifyIntrenal. We derive its value using an anomymous method.
If I see the code, since I do not assign any value to changedTypes, so as per my understanding the code if (changedTypes == null) should
always be true. But this is not the case when I debug.
Can someone explain me how does this works here?
private void Notify( Notification notification )
{
var nameDto = GetNameDto();
foreach (var subscription in _subscriptionsDictionary)
{
var callback = subscription.Key;
var subscribedTypes = subscription.Value;
NotifyIntrenal( notification, callback, changedTypes =>
{
if (changedTypes == null)
return subscribedTypes;
if (!changedTypes.Any())
return subscribedTypes;
return changedTypes.Intersect(subscribedTypes);
}, nameDto);
}
}
Thanks & Regards
changedTypes is not an argument to NotifyInternal. It is the parameter for the anonymous method.
This whole method is the argument for NotifyInternal.
The code inside that lambda is not executed at this point. It will only be executed if some line in NotifyInternal calls it. So there has to be code line in NotifyInternal executing the anonymous method:
void NotifyInternal(Notification notification, Callback callback, Func<IEnumerable<Type>, IEnumerable<Type>> function, string nameDto)
{
// ... some code
// execute the lambda
var result = function(mychangedtypesvariable);
// ... more code
}
Only then the code inside the lambda is executed, using the pass argument (mychangedtypesvariable in that example). So if this will be null you cannot decide from the snippet you see.
changedTypes is just a paremeter for your anonymous method, not for NotifyIntrenal. The latter however calls that anonymous method and fills the parameter (if required) appropriately. In your case the anonymous method expects an IEnumerable<MyType> and returns an IEnumerable<MyType>.
NotifyIntrenal(string arg1, string arg2, Func<IEnumerable<MyType>, IEnumerable<MyType>> func) {
// do something
var list = new List<MyType> { ...}
// execute the delegate with the list
IEnumerable<MyType> result = func(list);
}
So actually changedTypes is provided by NotifyIntrenal, not given to it. How you create that argument within the method is up to you.
private static void AssertNotNullAndAreEqual<T, TK>(T expected, TK actual)
{
Assert.IsNotNull(expected);
Assert.AreEqual(expected, actual);
}
I can call it using:
AssertNotNullAndAreEqual(expected.FirstName, actual.FirstName);
Is there any simple way that I can know the "FirstName" text of the expected object from within this method?
I'd need it for logging purposes and giving proper error messages from within this method.
The C# caller information doesn't help here.
I would rethink that approach, because this might bite back at some point - but if you're really keen on getting some degree of automation, you could try this:
private static void AssertNotNullAndAreEqual<T, TK>(Expression<Func<T>> expected,
Expression<Func<TK>> actual)
{
var memberExpression = expected.Body as MemberExpression;
if (memberExpression != null)
{
var expectedMemberName = memberExpression.Member.Name;
var expectedVal = expected.Compile()();
var actualVal = actual.Compile()();
Assert.IsNotNull(expectedVal);
Assert.AreEqual(expectedVal, actualVal);
//...
}
}
Now your calls would have to look as follows:
AssertNotNullAndAreEqual(() => expected.FirstName, () => actual.FirstName);
Few more caveat
a lot of stuff will not be checked until compile time (luckily type-safety is preserved). It's easy to write calls that will compile correctly, but fail at runtime.
as this is written, it won't work with variables - but if you decide to go this way, it would be pretty easy to write.
Please use at your own discretion :)
If you're using ToString() for another purpose (which I assume you are), you can define an interface and use it as a type constraint on AssertNotNullAndAreEqual(...), or alternately check to see if the objects passed to AssertNotNullAndAreEqual(...) have the interface.
You define an interface, say IDebugString, which has a ToDebugString() method, then you call that to retrieve the info to log.
Based on the following question, I found some odd behaviour of the c# compiler.
The following is valid C#:
static void K() {}
static void Main()
{
var k = new Action(new Action(new Action(K))));
}
What I do find strange is the compiler 'deconstructing' the passed delegate.
The ILSpy output is as follows:
new Action(new Action(new Action(null, ldftn(K)), ldftn(Invoke)).Invoke);
As one can see, it automatically decides to use the Invoke method of the delegate. But why?
As it is, the code is unclear. Do we have a triply-wrapped delegate (actual) or is the inner delegate just 'copied' to the outer ones (my initial thought).
Surely if the intent was like the compiler emitted the code, one should have written:
var k = new Action(new Action(new Action(K).Invoke).Invoke);
Similar to the decompiled code.
Can anyone justify the reason for this 'surprising' transformation?
Update:
I can only think of one possible use-case for this; delegate type conversion. Eg:
delegate void Baz();
delegate void Bar();
...
var k = new Baz(new Bar( new Action (K)));
Perhaps the compiler should emit a warning if the same delegate types are used.
The spec (section 7.6.10.5) says:
The new delegate instance is initialized with the same invocation list as the delegate instance given by E.
Now suppose the compiler translated it to something similar to your suggestion of:
new Action( a.Target, a.Method)
That would only ever create a delegate with an invocation list of a single method call. For a multi-cast delegate, it would violate the spec.
Sample code:
using System;
class Program
{
static void Main(string[] args)
{
Action first = () => Console.WriteLine("First");
Action second = () => Console.WriteLine("Second");
Action both = first + second;
Action wrapped1 =
(Action) Delegate.CreateDelegate(typeof(Action),
both.Target, both.Method);
Action wrapped2 = new Action(both);
Console.WriteLine("Calling wrapped1:");
wrapped1();
Console.WriteLine("Calling wrapped2:");
wrapped2();
}
}
Output:
Calling wrapped1:
Second
Calling wrapped2:
First
Second
As you can see, the real behaviour of the compiler matches the spec - your suggested behaviour doesn't.
This is partly due to the somewhat odd "sometimes single-cast, sometimes multi-cast" nature of Delegate, of course...
When you try to treat a delegate as a method, the compiler actually uses the delegate's Invoke() method. So, for example, the two lines below compile to the exact same IL (both call Invoke()):
k();
k.Invoke();
I assume the oddity you're seeing is a consequence of this. The delegate constructor expects a method (or rather, a method group), but it gets a delegate instead. So it treats it as a method and uses the Invoke() method.
As for the meaning, it is delegate that calls delegate that calls the actual method. You can verify this yourself by accessing the delegate's Method and Target properties. In the case of the outer-most delegate, Method is Action.Invoke and Target the inner delegate.
delegate is a class
Action delegate has a constructor like so
public extern Action(object #object, IntPtr method);
Since K is a static method there is no need to pass object to inner most action instance as first argument and hence it passes null
Since second argument is pointer to function therefore it passes pointer of K method using ldftn function
for the remaining Action instances the object is passed is inner Action and the second parameter is the Invoke method since when you call a delegate you're actually calling the Invoke method
Summary
var action = new Action(K) => Action action = new Action(null, ldftn(K))
new Action(action) => new Action(action, ldftn(Action.Invoke))
I hope this explains what is happening?