Open Delegate fails when trying to access Int or DateTime property - c#

I have been testing out using delegates instead of reflection for some object sorting and it was working good for string properties, but if I try an Int (or DateTime) it fails and throws
Error binding to target method.
class Program
{
static void Main(string[] args)
{
var sample = new SampleClass() { Num = 13, Text = "Sample" };
Console.WriteLine(ReadProp(sample,"Text")); //Works
Console.WriteLine(ReadProp(sample, "classProp")); //Works
Console.WriteLine(ReadProp(sample, "Num")); //Throws 'Error binding to target method.'
}
//Use a Delegate to improve speed of accessing property instead of reflection
static object ReadProp(SampleClass obj, string propName)
{
var method = obj.GetType().GetProperty(propName).GetGetMethod();
var getForProp = (Func<SampleClass, object>)Delegate.CreateDelegate(typeof(Func<SampleClass, object>), null, method);
return getForProp(obj);
}
}
//A sample class for illustration purposes
class SampleClass
{
public string Text { get; set; }
public int Num { get; set; }
public SampleClass classProp { get; set; }
}
My question is: Why does it work for strings or other classes but not for Int or DateTime?
I can see that if I change my Func<SampleClass, object> to Func<SampleClass, int> it will then work for my Int but I expected object would work for both.

Why does it work for strings or other classes but not for Int or DateTime?
Because a method which returns an int isn't a method which returns an object reference. There has to be a boxing conversion - so something's got to do that, and Delegate.CreateDelegate is trying to provide a delegate which just invokes the delegate and returns the result, with no value conversion involved.
It's slightly painful to do, but basically I suspect you should either be building a Func with an appropriate return value and using that directly or you should go via a wrapper delegate which calls the "real" delegate and boxes the result.
(Note that in your sample code, you're creating the delegate each time, which is going to be no faster than reflection. Hopefully your real code is more sensible :)
If you look at this code from protobuf-csharp-port you'll see I've got a method to do exactly this - a lambda expression calls the strongly-typed delegate, and then uses the implicit conversion to object (boxing where necessary) to provide the value. You should be able to use something very similar. However, if you're sorting do you really want a Func<T, object>? If you use a strongly-typed delegate instead, you may be able to avoid all this boxing.

Related

Faster calling of methods using reflection

I'm porting over some old code from AS3 (via Haxe) to C#.
Parts of the code are transpiled, others I have manually rewritten in C#. One of these parts is the event dispatching.
I have event listeners registering to an event dispatcher, all listeners have a signature like this:
public void handleSomething(Event e)
// they may also use a subclass of Event as a parameter
public void handleAnother(MouseEvent e)
The events keep a small amount of data and a type:
public class Event {
public const string ENTER_FRAME = "enter_frame";
public const string RESIZE = "resize";
public const string CHANGE = "change";
readonly string type;
public Event(string type) {
this.type = type;
}
}
I keep a list keyed on the particular event type (a string, due to legacy reasons), once an event is dispatched I find the appropriate handlers keyed with that string and call the them with the event data.
I am currently using reflection to do this, but it is proving to be prohibitively slow. I have found several threads that share this problem.
My particular issue is that the method signature varies, if it was always an Event as a parameter I could use the solutions provided, but alas.
I'd be fine with trading some memory/time at setup to get subsequent calls to be faster. I can get a reference to the method and work out what type it expects, but I'm unsure how to store and call this later?
You can create and compile LINQ expression for each handler method and cache it for future use.
public class CompiledDelegate
{
// Assume that there is one one method per handler class type, add method name to dictionary key if necessary
private static Dictionary<Type, CompiledDelegate> _Cache = new Dictionary<Type, CompiledDelegate>();
public static CompiledDelegate Get(Type handlerType, string methodName)
{
CompiledDelegate result;
if (!_Cache.TryGetValue(handlerType, out result))
{
var method = handlerType.GetMethod(methodName);
// determine type of single method parameter
var paramType = method.GetParameters().Single().ParameterType;
// create expression tree (object h, object p) => ((handlerType)h).MethodName((paramType)p)
var exprHandler = Expression.Parameter(typeof(object), "h");
var exprParam = Expression.Parameter(typeof(object), "p");
var lambda = Expression.Lambda(
Expression.Call(
Expression.TypeAs(exprHandler, handlerType), // instance, cast object to handlerType
method, // method
Expression.TypeAs(exprParam, paramType) // parameter, cast object to paramType
),
exprHandler, exprParam // lamda params
);
result = new CompiledDelegate()
{
Method = method,
// compile expression
Compiled = (Action<object, object>)lambda.Compile()
};
_Cache.Add(handlerType, result);
}
return result;
}
public MethodInfo Method { get; private set; }
public Action<object, object> Compiled { get; set; }
}
Once you have hander instance, you can call its method via compiled delegate:
CompiledDelegate.Get(handler.GetType(), "handlerSomething").Compiled(handler, mouseEvent)
You can pre-generate CompiledDelegate for each of handlers and add to the dispatch table together with handlers themselves.
Calling method via compiled delegate (once it's compiled of course) is approximately 10 times faster then calling same method via reflection.

Implicit conversion from IEnumerable<int> to IEnumerable<dynamic>

I haven't used dynamic much in C# so far, so I came across a (small) problem when trying to create a simple WebGrid-like component for learning purposes.
The normal WebGrid takes as its data source an IEnumerable<dynamic>, so I emulated that. Then I created a view like the following:
#model IEnumerable<int>
#{
MyWebGrid grid = new MyWebGrid(Model);
}
In the MVC project, this leads to a runtime conversion error, so I created a small console application (this doesn't compile of course):
class Program
{
class Foo { public int Id { get; } }
static void Main()
{
CheckConversion(new List<int>().AsEnumerable()); // Error
CheckConversion(new List<Foo>()); // works
int x = 5;
CheckSingleParameterConversion(x); // works
}
private static void CheckConversion(IEnumerable<dynamic> source) { }
private static void CheckSingleParameterConversion(dynamic val) { }
}
The error (in short): Cannot convert from IEnumerable<int> to IEnumerable<dynamic>.
What is the exact reasoning behind these differing behaviors? I know that dynamic is a reference type and could thus understand why there might be some problem with the IEnumerable<int> here, but why does it work in the single parameter case then?
Problem is not in dynamic itself, it's all about variance.
As said in MSDN
Variance applies only to reference types; if you specify a value type
for a variant type parameter, that type parameter is invariant for the
resulting constructed type.
So IEnumerable<int> cannot be casted to IEnumerable<dynamic>, because int is a value type and dynamic is just an object marked with special attribute.

Using Explicit Cast in an Extension Method

I have a weird problem when I'm trying to cast an object via an extension method. I have a class where I wrap some functionality around an IPAddress.
// Dumbed down version of class
public sealed class PrefixLengthIPAddress
{
public static explicit operator IPAddress(PrefixLengthIPAddress address)
{
return (address != null) ? address._address : null;
}
public PrefixLengthIPAddress(IPAddress address)
{
_address = address;
_length = address.GetLength();
}
private readonly ushort _length;
private readonly IPAddress _address;
}
I don't like the look of all the parenthesis to extract the IPAddress out of the object:
var family = ((IPAddress)prefixLengthAddress).AddressFamily;
I'd rather be able to do something like this:
var family = prefixLengthAddress.CastAs<IPAddress>().AddressFamily;
In order to do this I wrote the following Extension Method:
public static T CastAs<T>(this object value) where T : class
{
return (T)value;
}
Unfortunately with this I'm getting an InvalidCastException:
var family = ((IPAddress)prefixLengthAddress).AddressFamily; // Works
var family = prefixLengthAddress.CastAs<IPAddress>().AddressFamily; // InvalidCastException
I understand that in this particular case I could simply expose the IPAddress with a getter, but we also have more complex explicit casts that I would like to do this with.
EDIT
Thanks to Chris Sinclair's comment on using dynamic I have updated the extension method to look like:
public static T CastAs<T>(this object value)
{
return (T)((dynamic)value);
}
There is some overhead with using dynamic, but it is more than fast enough for my needs. It also seems to work with all the basic type casting I've tried.
In the first sample you are accessing the user defined conversion. This is only available when the cast operator knows the type of the input is PrefixLengthAddress. In the generic code the compiler only knows the type object and T. There is no way it can access the conversion defined on PrefixLengthAddress in this scenario.
In this scenario what you're doing is much closer to mapping vs. casting since it's actually creating a new value. In terms of LINQ you would want to use Select vs. Cast.

Generate Generic Type At Runtime

I am wondering if it is possible to use the type of one variable to set as the type of another generic variable?
For example, say I have this code:
public class Foo: IBar<ushort>
{
public FooBar()
{
Value = 0;
}
public ushort Value { get; private set; }
}
I also have this class:
public class FooDTO<TType> : IBar<TType>
{
public TType Value { get; private set; }
}
In these examples, in the interface for IBar has the property
TType Value;
Then in my code I have this
var myFoo = new Foo();
var fooDataType = myFoo.Value.GetType();
//I know this line of code does not compile, but this is what I am looking to be able to do
var myFooDTO= new FooDTO<fooDataType>();
Is what I am looking for possible? Would it be too slow for high use code (because of using reflection.
You can do this via Reflection, by using Type.MakeGenericType.
This will have some overhead due to reflection, so you'd need to profile it to see if that will be an issue for you.
Why not use Method type inference:
public class FooDTO<TType> {
public TType Value { get; private set; }
}
public class Foo : FooDTO<ushort> { }
static FooDTO<T> GetTypedFoo<T>(T Obj) {
return new FooDTO<T>();
}
static void Main(string[] args) {
Foo F = new Foo();
var fooDTO = GetTypedFoo(F.Value);
}
Always when I read "generic" and "runtime" in one sentence, I always thing "bad design" or "doesnt understant what generic means". Possibly both.
Generic parameter is integral part of the type. So saying "Generate Generic Type At Runtime" is same as "Generate Foo class at runtime". You are either looking for reflection or change design of your algorithm.
Also var keyword is not going to help you in this case. Forget about it.
You're looking for compile-time reflection, a feature that C# doesn't have. So if you're looking for performance optimizations, the solutions are worse than the problem.
D does have this feature, though; you can easily write
int x = 0;
typeof(x) y = x + 2;
or even much more complicated expressions in D, and it's all evaluated at compile-time.
The core of what you want is:
var type = typeof(FooDTO<>).MakeGenericType(fooDataType);
object obj = Activator.CreateInstance(type);
however, you'll notice that this is reflection, and pretty much ties you to object. The usual workaround to this is to have access to a non-generic version of the API, so that you can work with object - for example (with the addition of a non-generic IBar):
IBar bar = (IBar)Activator.CreateInstance(type);
You can of course move the runtime/generics hit higher up - perhaps into a generic method; then everything in the generic method can use T, and you can use MakeGenericMethod to execute that method in the context of a particular T known only at runtime.

Passing Delegate object to method with Func<> parameter

I have a method Foo4 that accepts a parameter of the type Func<>. If I pass a parameter of anonymous type , I get no error. But if I create and pass an object of the type 'delegate' that references to a Method with correct signature, I get compiler error. I am not able to understand why I am getting error in this case.
class Learn6
{
delegate string Mydelegate(int a);
public void Start()
{
Mydelegate objMydelegate = new Mydelegate(Foo1);
//No Error
Foo4(delegate(int s) { return s.ToString(); });
//This line gives compiler error.
Foo4(objMydelegate);
}
public string Foo1(int a) { return a.ToString();}
public void Foo4(Func<int, string> F) { Console.WriteLine(F(42)); }
}
It works if you pass a reference to the method directly:
Foo4(Foo1);
This is because actual delegates with the same shape are not inherently considered compatible. If the contracts are implicit, the compiler infers the contract and matches them up. If they are explicit (e.g. declared types) no inference is performed - they are simply different types.
It is similar to:
public class Foo
{
public string Property {get;set;}
}
public class Bar
{
public string Property {get;set;}
}
We can see the two classes have the same signature and are "compatible", but the compiler sees them as two different types, and nothing more.
Because Func<int, string> and MyDelegate are different declared types. They happen to be compatible with the same set of methods; but there is no implicit conversion between them.
//This line gives compiler error.
Foo4(objMydelegate);
//This works ok.
Foo4(objMydelegate.Invoke);
depends on the scenario, but in the general case there's no reason to keep around the Mydelegate type, just use Func<int, string> everywhere :)

Categories

Resources