I have a property declared as type dynamic
public dynamic Data {get;set;}
later in some method the type of data becomes System.Collections.Generic.List
so if use Data.AsQueryable() i get "System.Collections.Generic.List<Entity1 does not contain a definition for 'AsQueryable' " error.
The result has to be converted to Iqueryble and i am using the methods defined in Dynamic.Linq.
How should i proceed?
Currently, dynamic doesn't work well with extension methods.
7.6.5.2 Extension method invocations
...if the normal processing of the
invocation finds no applicable
methods, an attempt is made to process
the construct as an extension method
invocation. If expr or any of the args
has compile-time type dynamic,
extension methods will not apply
As is mentioned in this question, the static context (applicable using directives) would have to be made available at run-time for every dynamic call to figure out which extension methods may apply, which is currently not implemented.
Have you tried calling the extension method as a 'normal' static method instead? E.g. (please modify if you intended to call a different method): System.Linq.Queryable.AsQueryable(Data)
Related
As far as I know, the C# extension method has the attribute of 'System.Runtime.CompilerServices.ExtensionAttribute'
so i wrote simple test and I check with ilspy and this does not exist there.
I also on creating an object instance and investigating the instance method - I can't recognize if some method is an extension method or not.
I also look on the il viewer but on the viewer i see the 'System.Runtime.CompilerServices.ExtensionAttribute'
I looking for another way to know if some object/assembly method are extension method from runtime code.
(.net core 6.0)
Pretty easily, just check whether a given MethodInfo has the ExtensionAttribute applied to it using the GetCustomAttributes(Type, bool) method
So:
public static bool IsExtensionMethod(this MethodInfo method)
{
// The 'false' is because static classes must derive from 'object'
// So checking for inherited attributes is unnecessary
return method.GetCustomAttributes(typeof(ExtensionAttribute), false).Length > 0;
}
Demo
FWIW I recommend not looking at IL directly (unless you really need to), instead I recommend you use something like Sharplab to decompile the C# code to actually see what gets compiled, as "code lowering" (sometimes also called desugaring/ stripping syntactic sugar away) is one of the first steps the compiler does
in a for loop I receive results from a db as dynamic type
dynamic {system.collections.generic.List<object>}
I need to collect these results into one single variable.
I tried defining a variable
dynamic results = new List<object>();
and then
var queryResults = _dbManager.Query(query);
results = results.Concat(queryResults);
but I have this exception:
System.Collections.Generic.List<object> does non contain a definition for 'Concat'
I can't find a solution. Do you how can I do this? Thanks!
The problem is that dynamic types and extension methods don't work well together (read the explanation of Eric Lippert on the why). You have to call the extension method yourself as a static method (which it actually is):
var l = Enumerable.Concat(results, queryResults);
Concat is an extension method. Extension methods are a compiler syntactic sugar. Essentially the compiler chooses the appropriate static method to call based on the static type of the object on which you call the extension method. But dynamic variable have no static type so the compiler cannot search for extension methods.
Edit: Patrick Hofman's solution should work, but it is not LINQ that does not work well with extension methods. In fact LINQ is heavily relying on extension methods. The problem is LINQ assumes static typing of variable (and actually is the very reason to use LINQ: get the compiler validate your code for type safety)
I'm using BitFactory logging, which exposes a bunch of methods like this:
public void LogWarning(object aCategory, object anObject)
I've got an extension method that makes this a bit nicer for our logging needs:
public static void LogWarning(this CompositeLogger logger,
string message = "", params object[] parameters)
Which just wraps up some common logging operations, and means I can log like:
Logging.LogWarning("Something bad happened to the {0}. Id was {1}",foo,bar);
But when I only have one string in my params object[], then my extension method won't be called, instead the original method will be chosen.
Apart from naming my method something else, is there a way I can stop this from happening?
The rules about how overloaded methods are resolved to one (or an error) are complex (the C# specification is included with Visual Studio for all the gory details).
But there is one simple rule: extension methods are only considered if there is no possible member that can be called.
Because the signature of two objects will accept any two parameters, any call with two parameters will match that member. Thus no extension methods will considered as possibilities.
You could pass a third parameter (eg. String.Empty) and not use it in the format.
Or, and I suspect this is better, to avoid possible interactions with additions to the library (variable length argument list methods are prone to this) rename to LogWarningFormat (akin to the naming of StringBuffer.AppendFormat).
PS. there is no point having a default for the message parameter: it will never used unless you pass no arguments: but that would log nothing.
Declared methods are always preceding extension methods.
If you want to call the extension regardless of the declared method, you have to call it as a regular static method, of the class that declared it.
eg:
LoggerExtensions.LogWarning(Logging, "Something bad happened to the {0}. Id was {1}",foo,bar);
I assume that the extension is declared in a class named LoggerExtensions
Provided that I think a method with a different name is the way to go (easier to read and maintain), as a workaround you could specify parameters as a named parameter:
logger.LogWarning("Something bad happened to the {0}.", parameters: "foo");
So, i have an assembly that i loaded into the interface, and it works perfectly:
MarshalByRefObject pluginObject = ...
ecko.Plugins.Interface.Plugin plug = pluginObject as ecko.Plugins.Interface.Plugin;
but, allthough i will have alot of methods in the interface, i will have to execute methods that are dynamic, and determined from information in the interface.. so basically, i need to call methods that are not in my interface, and i wont know the name of until last minute..
this is what i have tried (using the "Execute" methods as an example):
plug.GetType().GetMethod("Execute").Invoke((what-the-hell-do-i-put-here), new object[] { });
am i on the right track? please guide me :)
thanks.
If you want to use Reflection then the missing piece in your code is:
MethodInfo meth = plug.GetType().GetMethod("Execute");
meth.Invoke(plug, new object[] { });
The first parameter of the Invoke method should be the instance that you want to invoke the method on. This is required because meth is just an abstract description of the method (and is not associated with any instance). This is useful if you want to call the method on multiple instances (you could cache the meth value).
If you're using C# 4.0, then you can use the new dynamic feature (assuming that "Execute" is a name that does not change):
dynamic plugDynamic = plug;
plugDynamic.Execute( /* arguments */ );
If a variable is declared as dynamic in C# 4.0, then you can call any methods you want and the method resolution will be done at runtime (similar to Reflection, but a bit more complicated and a bit more efficient).
I've seen this syntax a couple times now, and it's beginning to worry me,
For example:
iCalendar iCal = new iCalendar();
Event evt = iCal.Create<Event>();
It's a Generic Method, Create is declared with type parameters, and check this links for more information:
An Introduction to C# Generics
Generics (C# Programming Guide)
Generic Methods
It's calling a generic method - so in your case, the method may be declared like this:
public T Create<T>()
You can specify the type argument in the angle brackets, just as you would for creating an instance of a generic type:
List<Event> list = new List<Event>();
Does that help?
One difference between generic methods and generic types is that the compiler can try to infer the type argument. For instance, if your Create method were instead:
public T Copy<T>(T original)
you could just call
Copy(someEvent);
and the compiler would infer that you meant:
Copy<Event>(someEvent);
It's the way you mention a generic method in C#.
When you define a generic method you code like this:
return-type MethodName<type-parameter-list>(parameter-list)
When you call a generic method, the compiler usually infers the type parameter from the arguments specified, like this example:
Array.ForEach(myArray, Console.WriteLine);
In this example, if "myArray" is a string array, it'll call Array.ForEach<string> and if it's an int array, it'll call Array.ForEach<int>.
Sometimes, it's impossible for the compiler to infer the type from the parameters (just like your example, where there are no parameters at all). In these cases, you have to specify them manually like that.
It is a generic method that implements the Factory Method pattern.
This syntax is just applying generics to a method. It's typically used for scenarios where you want to control the return type of the method. You will find this kind of syntax a lot in code that uses a IoC framework.