Why VS2010 IntelliSense fails when chaining methods with dynamic args - c#

I would like some explanation of you experts in C# 4.0 dynamic.
I have a fluent builder class to help configure an object before creating it. This interface has a method SetParameters(...):
public FluentBuilder<TInterface> SetParameters(dynamic parameters)
{
_parameters = parameters;
return this;
}
I'm doing this to consume the fluent interface:
var order = new Order();
/* Setting up parameters */
dynamic parameters = new ExpandoObject();
parameters.Transaction = transactionObj;
parameters.CurrentPrincipal = Thread.CurrentPrincipal;
var proxiedOrder = ObjectProxyFactory
.Configure<IOrder>(order)
.FilterMethods(o => o.InsertOrder())
.AddPreDecoration(AppConcerns.JoinSqlTransaction)
.AddPreDecoration(AppConcerns.EnterLog)
.AddPostDecoration(AppConcerns.ExitLog)
.AddPostDecoration(AppConcerns.SecurityCheck)
.SetParameters(parameters)
.Teste() //this method doesn't exist in the fluent builder
.CreateProxy();
var result = proxiedOrder.InsertOrder();
As commented in the above snippet, the method called Teste() doesn't exists in the fluent interface, but intelissense allow write anymethod after I call SetParameters like it returning dynamic, but as you see in code, SetParameters returns FluentInterface that is not dynamic.
The code above compiles sucessfully by in runtime will fail because in runtime the method Teste() will not be found in FluentBuilder class.
To resolve this problem in design-time, and to get correct Intelissense, I need to cast the parameter to the ExpandoObject class:
var proxiedOrder = ObjectProxyFactory
.Configure<IOrder>(order)
.FilterMethods(o => o.InsertOrder())
.AddPreDecoration(AppConcerns.JoinSqlTransaction)
.AddPreDecoration(AppConcerns.EnterLog)
.AddPostDecoration(AppConcerns.ExitLog)
.AddPostDecoration(AppConcerns.SecurityCheck)
.SetParameters((ExpandoObject)parameters) //cast to ExpandoObject
.Teste() //now intelissense is giving me an "red" error and solution will not compile
.CreateProxy();
var result = proxiedOrder.InsertOrder();
I've found that, anytime I pass a C# dynamic parameter in any method chaining, after that method receiving the dynamic parameter, the subsequent calls to methods will behave like returning a C# dynamic object, even if the return type of the method it's not dynamic.
Is it a bug ? Or is this expected to happens ?

It's expected to happen. Any method call involving a dynamic argument is resolved dynamically - the exact overload can't be determined until execution time, so the return type is unknown at compile time, so it's treated as being dynamic. In some cases the C# compiler could infer more information (e.g. if it's a static method call) but for simplicity it doesn't. Only a variable few expressions involving dynamic values have non-dynamic types. (From memory, the is operator is always bool, and a constructor is always assumed to return the type being constructed.)
EDIT: I've finally found the spec reference. From section 7.6.5:
An invocation-expression is dynamically bound (ยง7.2.2) if at least one of the following holds:
The primary-expression has compile-time type dynamic.
At least one argument of the optional argument-list has compile-time type dynamic and the primary-expression does not have a delegate type.
In this case the compiler classifies the invocation-expression as a value of type dynamic.

Related

What is the value being passed into this lambda expression?

Forgive me if this is a stupid question but I am not sure where to look. I have this code that compiles fine:
static int Main(string[] args)
{
var parserResult = CommandLine.Parser.Default.ParseArguments<Options>(args);
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
parserResult.WithNotParsed<Options>(errs =>
{
var helpText = HelpText.AutoBuild(parserResult, h =>
{
return HelpText.DefaultParsingErrorsHandler(parserResult, h);
}, e =>
{
return e;
});
Console.WriteLine(helpText);
ReturnErrorCode = ErrorCode.CommandLineArguments;
});
return (int)ReturnErrorCode;
}
My query has to do with this line of code:
parserResult.WithParsed<Options>(options => OnSuccessfulParse(options));
I understand that with a Lambda Expression the value on the left of the => is the value and value on the right is the expression.
What exactly is options? Why does it compile? It works absolutely fine. But what is it?
I don't know if this helps:
I might be barking up the wrong tree with my understanding of this. I admit I am struggling with the concept. Any explanation appreciated.
I see several questions but I can't explain it in my situation.
Update
OnSuccessfulParse declaration is:
private static void OnSuccessfulParse(Options options)
The WithParsed code is provided here
Lambda expression is the delegate of type Action<Options>. It is a callback from the parser into your code to inform you that the parse has been successful, and pass you Options object obtained as the result of the parse.
As far as options goes, it's just a name that you picked for the parameter to be passed into OnSuccessfulParse method. It is completely unnecessary here - this method group equivalent call will compile and run just the same:
parserResult.WithParsed<Options>(OnSuccessfulParse);
Here is the definition of WithParsed<T> method from github project:
public static ParserResult<T> WithParsed<T>(this ParserResult<T> result, Action<T> action)
{
var parsed = result as Parsed<T>;
if (parsed != null) {
action(parsed.Value);
}
return result;
}
This method is rather straightforward: it takes parse result, tries casting it to a successful parse, and if the cast is valid, calls a delegate that you supply. The WithNotParsed<T> method casts to unsuccessful NotParsed<T> result, and makes a call if the cast is valid.
That's a C# (.Net) way of representing function blocks.
Essentially an Action<Type> is an invocable type that roughly means pass an instance of Type in and execute the block.
E.g. we can write
public void Do(){
this.CallStuff(s => Console.WriteLine(s)); // or you can use a method group and do this.CallStuff(Console.WriteLine);
}
public void CallStuff(Action<string> action){
var #string = "fancy!";
action(#string);
}
In this case the s type is string.
In your example there is a type called Options defined somewhere and it is passed into an action.
Additionally, if you look at decompiled code, anonymous method blocks passed to actions are compiled as static anonymous types inside your class (because c# does not support dynamic code blocks, like, for example, obj-c does).
Another thing to look into are Func<out type> -> these are essentially the same as Action<> except the LAST type in the generic definition is the type they return.
UPD
#elgonzo raises a good point - Action<> and Func<> are actually just delegates; meaning that you can define a real method and pass it along as an Action or Func and then no anonymous static class will be compiled.
However in practice you will see that a lot of code defines those inline, and then the in-line code block needs to reside within a method somewhere, so the compiler puts it into the statis anonymous class.
What exactly is options?
options is i/p parameter to delegate represented by lambda expression
Why does it compile?
Simply because it adheres all syntactical and semantic rules of compiler ;) Like (x)=>x+1 is lambda expression to represent Func<int,int> (there can be another delegate to match same signature as well)
If your method expects Func<int,int> as parameter and argument passed is (x)=>x+1 then compiler infers this as x of type int. Compiled IL code would be equivalent to passing instance of delegate as an argument to method. Like :
call((x)=>x+1) will be compiled to call(new Func<int,int>(myMethod)) where call method definition is :
void Call(Func<int,int> someparam) {}
But what is it?
I think above response should have addressed this query.

Passing var as T parameter

I am trying to build OrderBy expression the problem is when I pass var object to TSource the Type for TSource will be object not the Actual Column type
for example the Actual type is int but TSource type is object.
Type tblType = tblObj.GetType();
PropertyInfo propinfo;
propinfo = tblType.GetProperty(ColumnName);
if (propinfo == null)
{
return null;
}
var instance = Activator.CreateInstance(propinfo.PropertyType);
result = result.OrderBy(GetOrder(item.ColumnName, tblObj, instance));
and here is the lambda expression builder
public Expression<Func<T, TSource>> GetOrder<T,TSource>(string field, T item,TSource source)
{
if (string.IsNullOrEmpty(field))
{
return null;
}
var param = Expression.Parameter(typeof(T), "c");
Expression conversion = Expression.Convert(Expression.Property
(param, field), typeof(TSource));
return Expression.Lambda<Func<T, TSource>>(conversion, param);
}
When not sure of the type, you can use dynamic so the type will be found at runtime level.
result = Enumerable.OrderBy(
result,
GetOrder(item.ColumnName, tblObj, (dynamic)instance));
You either must use dynamic keyword or use reflection.
But, you can solve your probelm with dynamic more easily.
The only problem is that, extension methods will not be dynamically dispatched.
So, you must call extension method as simple static method:
result = Enumerable.OrderBy(
result,
GetOrder(item.ColumnName, tblObj, instance as dynamic));
Also, you can ask a question "Why extension methods can not be dynamically dispatched?"
The asnwer by #EricLippert:
That means that in order to get a dynamic extension method invocation
resolved correctly, somehow the DLR has to know at runtime what all
the namespace nestings and "using" directives were in your source
code. We do not have a mechanism handy for encoding all that
information into the call site. We considered inventing such a
mechanism, but decided that it was too high cost and produced too much
schedule risk to be worth it.
So, CLR must find the namespace which holds extension method. CLR searches this and it it finds the method namespace, then it just changes for example, result.OrderBy to Enumerable.OrderBy(result, ...). But, in case of dynamic keyword, DLR(Dynamic Language Runtime) must find the class of this method in runtime, again based on included namespaces. Microsoft team rightly thinks that it is too high cost and avoids to implement it.
Method Activator.CreateInstance(Type type) returns object, not int.
May be you should unbox it to int before use;
Follow the documentation Activator.CreateInstance return object, so you have to cast it to destination type or you can use dynamic type, but than compiler can't check types.

C# : AsQueryable() vs AsQueryable<type>()

I am having problem while using AsQueryable, I found some example in which casting i.e. AsQueryable required for this extension and in some example directly as AsQueryable(). I check both case with Stopwatch and concluded with almost same result for multiple investigation.
Lets take example:
//With AsQueryable()
var studentId = dbContext.Students.AsQueryable().Where(a=>a.Name == "Abc").Select(a=>a.Id).FirstOrDefault();
//With AsQueryable<Student>()
var studentId = dbContext.Students.AsQueryable<Student>().Where(a=>a.Name == "Abc").Select(a=>a.Id).FirstOrDefault();
What is difference between using AsQueryable() and AsQueryable<type>() and which is efficient?
When you call AsQueryable() without specifying generic parameter type it's inferred by compiler from an object you call it at.
var source = new List<int>();
var queryable = source.AsQueryable(); // returns IQueryable<int>
is equivalent to
var queryable = source.AsQueryable<int>();
Update
To answer question asked in comments:
Then what is the use for having two different way? Is there any particular situation when we have to use only one of it?
Yes, you can't specify type parameter explicitly when using anonymous types, because you don't have class name:
source.Select((x,i) => new { Value = x, Index = i }).AsQueryable();
And that's exactly why type inference was introduced: to let you call generic methods without specifying type parameters when using anonymous types. But because it works not only with anonymous types, and saves you unnecessary typing, it's very common to rely on type inference whenever it's possible. That's why you'll probably see AsQueryable() without type parameter most of the times.
Whenever possible, the compiler can do type inference for you:
http://msdn.microsoft.com/en-us/library/twcad0zb.aspx
And in that case, there's no difference, advantage, or penalty either way. Type inference just makes your life easier and your code shorter.
However, I've run into cases when consuming APIs where a type implements several interfaces, e.g.
IEnumerable<IMySimpleThing>, IEnumerable<IMyComplexThing>, IEnumerable<MyComplexThing>
and type inference isn't sufficient if you're trying to get at a specific interface, e.g.
IEnumerable<MyComplexThing>
So in that case, specifying type to the generic, like .AsQueryable<MyComplexThing>(), will do the trick.

NHibernate ISession.QueryOver() cannot infer type but ISession.Get() can.. Why is this?

In NHibernate, the following works perfectly fine:
Session.Get(repoType.ToString(), id))
But this:
Session.QueryOver(repoType.ToString(), func)
for some reason, does not. From the documentation, both methods take in the name of the entity as a string as the first parameter, but QueryOver complains with the following error message:
The type arguments for method 'NHibernate.ISession.QueryOver<T>(string, System.Linq.Expressions.Expression<System.Func<T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I'm fairly sure that this is being caused by the first parameter to QueryOver (the entityName parameter), and not the func parameter.
Why is it that ISession.Get can infer the entity type from the given entity name but ISession.QueryOver cannot?
This is not an issue with the nHibernate library, it's an issue with .NET generics and Linq expressions.
NHibernate might be capable of inferring the entity type, but you have to get the code to compile first. :-)
The signature for the QueryOver function is as follows:
IQueryOver<T, T> QueryOver<T>(string entityName, Expression<Func<T>> alias) where T : class;
Note that a Func<T> is not the same type as a System.Linq.Expressions.Expression<T>.
In your example, I assume you have declared a Func<T> as a separate variable, and the compiler is unable to figure out what to cast it too.
Here are some variations of the call:
// Defining the second parameter explicitly as an expression.
// This works
Company companyAlias = null;
System.Linq.Expressions.Expression < Func < Company >> expression = () => companyAlias;
var q1 = this.Session.QueryOver("Company", expression);
We can let the compiler turn an in-line lambda into an expression. This works too, and the compiler infers all of the type arguments.
var q2 = this.Session.QueryOver("Company", () => companyAlias);
It will fail if we use a plain function object instead of an expression.
Here, the compiler can't figure out how to make the Func<Company> fit into the generic expression. Hence the error "The type arguments cannot be inferred by the usage..."
Func<Company> func = () => companyAlias;
var q3 = this.Session.QueryOver("Company", func);
We help the compiler by explicitly stating the type. The code below will still fail, but we get a better error. "The best overload match for ... has some invalid arguments"
var q4 = this.Session.QueryOver<Company>("Company", func);
If possible, it's best to give it the type as a generic expression rather than the name. That way you avoid potential errors if you ever rename the type but forget to change the string in the function.
var q = session.QueryOver<Company>(() => companyAlias);
You don't even have to put the generic parameter in in this case.
var q = session.QueryOver(() => companyAlias);
However, I prefer to keep the generic parameter in, just for the sake of readability.

Reflection of generic method not working

I have a generic static method which registers a interface and I need to write that using c# reflection.
Services.AddService<ITBroker>(new TBrokerService());
I tried following code but it is not working
Type[] externTBrokerService = Assembly.LoadFrom("Business.dll").GetTypes();
Type[] externService = Assembly.LoadFrom("ServiceModel.dll").GetTypes();
Type iTBroker = externITBroker[12];
MethodInfo method = externService[1].GetMethods()[2];
//Gets Add Service method
MethodInfo generic = method.MakeGenericMethod(iTBroker);
//Make method generic
generic.Invoke(null,new object[] { externTBrokerService[0]});
//invoke the service
Above code gives me very generic exception of parameters.
What is the write way to write reflection for above code?
As it was in comments:
Note that externTBrokerService[0] is a Type and not an instance of that type.
Having that I feel a need to include sense of other comments as part of my answer.
Type iTBroker = externITBroker[12];
this is wrong! And sooner or later this will fail to find your type as the order of types in this collection is undetermined and can change. You should do it like this:
Type iTBroker = externITBroker.Single(x => x.Name == "ITBroker");
This is far form foolproof so be sure that the condition gives you unique result.
or simply load that type directly by (assuming that this is the AssemblyQualifiedName of your type):
Type.GetType("Business.ITBroker, Business");
To find method on your type there is a method Type.GetMethod one of its overloads will be sufficient to find your method.
To create instance of your type that needs to be passed as argument you can use
Activator.CreateInstance(brokerServiceType);

Categories