Dictionary of Action<T> Delegates - c#

I have object XML serialized messages coming into a class called MessageRouter. The XML contains the Type name it it was serialized from, and I need to be able to invoke different delegate methods depending on the type that are not known until runtime. I'm not extremely strong in generics so hopefully this will make sense to someone...
I'd like MessageRouter to provide a RegisterDelegateForType method like so:
myMessageRouter.RegisterDelegateForType(new Action<MySerializableType>(myActionHandler));
And then store the types, or the type's string representation in a Dictionary like this:
Dictionary<Type, Action<T>> registeredDelegates;
That way, I can do something like the following pseudocode, calling the type's assigned delegate and passing the deserialized object:
Type xmlSerializedType = TypeFromXmlString(incomingXml);
object deserializedObject = DeserializeObjectFromXml(xmlSerializedType, incomingXml);
// then invoke the action and pass in the deserialized object
registeredDelegates[xmlSerializedType](deserializedObject);
So my questions are:
How do you define a Dictionary that can contain a Type as a key and a generic Action<T> as a value, and have the RegisterDelegateForType method populate the dictionary?
If that's not possible, what's the best way to do this?

You cannot do this as described, for quite obvious reasons - even if somehow allowed, the last line of code in your example (the one which retrieves a delegate and then calls it) would be non-typesafe, as you're calling an Action<T> - which expects T as an argument - and yet passing it deserializedObject, which is of type object. It wouldn't work in plain code without a cast, why would you expect to be able to circumvent the type check for your case?
In the simplest case, you can do something like this:
Dictionary<Type, Delegate> registeredDelegates;
...
registeredDelegates[xmlSerializedType].DynamicInvoke(deserializedObject);
Of course this will allow someone to add a delegate which takes more or less than one argument to the dictionary, and you'll only find out at DynamicInvoke call, at run-time. But there isn't really any way to define a type which says "any delegate, but with 1 argument only". A better option might be this:
Dictionary<Type, Action<object>> registeredDelegates
and then registering types like this:
myMessageRouter.RegisterDelegateForType<MySerializableType>(
o => myActionHandler((MySerializableType)o)
);
The above snippet uses C# 3.0 lambdas, but you can do the same - if slightly more verbose - with C# 2.0 anonymous delegates. Now you don't need to use DynamicInvoke - the lambda itself will do the proper cast.
Finally, you can encapsulate the lambda creation into RegisterDelegateForType itself by making it generic. For example:
private Dictionary<Type, Action<object>> registeredDelegates;
void RegisterDelegateForType<T>(Action<T> d)
{
registeredDelegates.Add(typeof(T), o => d((T)o));
}
And now the callers can just do:
RegisterDelegateForType<MySerializableType>(myHandler)
So it's completely typesafe for your clients. Of course, you're still responsible for doing it right (i.e. passing an object of the correct type to the delegate you retrieve from the dictionary).

I am not sure that this completely answers your question, but here is a class I wrote that will accomplish what you want. I couldn't tell if you want your Action delegate to take a typed object or not, but in your pseudo code, you pass it an "object" to deserialize so I wrote my class accordingly and it therefore does not use generics:
public delegate void Action(object o);
public class DelegateDictionary {
private IDictionary _dictionary = new Hashtable();
public void Register<T>(Action action) {
_dictionary[typeof(T)] = action;
}
public Action Get<T>() {
return (Action)_dictionary[typeof(T)];
}
public static void MyFunc(object o) {
Console.WriteLine(o.ToString());
}
public static void Run() {
var dictionary = new DelegateDictionary();
dictionary.Register<string>(MyFunc);
// Can be converted to an indexer so that you can use []'s
var stringDelegate = dictionary.Get<string>();
stringDelegate("Hello World");
}
}
I believe this will accomplish what you want.

Related

List of generic delegates (e.g. System.Converter<TInput, TOutput>)

Is it possible to create a list of generic delegates, like System.Converter<TInput, TOutput>?
In java that could be List<Converter<?,?>>, but with Java's type erasure that's not very useful. Seems like in C# it should be possible to query the generic types after retrieval from the list and use the obtained instance to perform the desired conversion.
Elaborating on the question:
I have user supplied data in user provided formats which I know nothing about at compile time. Algorithms in my program know how to work with its own specific data types, of course. The goal is to have an equiavalent of Java's List<Converter<?,?>> where Converters can be installed (by me, or users) and queried automatically by the program to see if user's data can be converted to the required format for an algorithm.
This is very rudimentary and is only intended to show the basic concept.
It has:
A dictionary keyed on a 2-tuple of input and output types to hold converter instances.
A Register method to use for registering converters. Registering the same pair of types overwrites a previously registered converter. You can easily change it to be a no-op or an exception.
A Convert method to call a registered converter. It would be very trivial to create a TryConvert method if you needed it.
public static class ConverterContainer
{
private static readonly Dictionary<(Type, Type), Delegate> _converters = new Dictionary<(Type, Type), Delegate>();
public static void Register<TInput, TOutput>(Func<TInput, TOutput> converter)
{
if (converter is null)
throw new ArgumentNullException(nameof(converter));
_converters[(typeof(TInput), typeof(TOutput))] = converter;
}
public static TOutput Convert<TInput, TOutput>(TInput input)
{
if (_converters.TryGetValue((typeof(TInput), typeof(TOutput)), out var del))
{
Func<TInput, TOutput> converter = (Func<TInput, TOutput>)del;
return converter(input);
}
throw new InvalidOperationException("Converter not registered.");
}
}
What it does not have:
thread safety. This is left as an exercise to a serious implementor.
possibly other things I didn't take the time to consider.
How to use it:
At startup of your application, register converters, like registering services for dependency injection.
ConverterContainer.Register<long, int>(l => (int)l);
// ... etc.
And wherever you want to perform conversion between a registered pair of input/output types:
int x = ConverterContainer.Convert<long, int>(1000L)
Unfortunately, you do have to specify both type arguments here.
Addition from the OP:
To not have to specify the input parameter type (which is kind of the point of having a dynamic list of available conversions) use the following additional method in the sample ConverterContainer above (as #madreflection has suggested in the comments himself) :
public static TOutput Convert<TOutput>(object toConvert) {
if (toConvert is null)
throw new ArgumentNullException(nameof(toConvert));
if (Converters.TryGetValue((toConvert.GetType(), typeof(TOutput)), out Delegate conv)) {
object o = conv.DynamicInvoke(toConvert);
return (TOutput) o;
}
throw new InvalidOperationException($"Converter not registered for types: {toConvert.GetType().Name} -> {typeof(TOutput).Name}");
}
You can now throw in any random object instance and see if the conversion to your desired type is possible.
In C# all the converters in the list will share the same type parameters (TInput, TOutput). Unless you have a non generic interface IConverter, you will not be able to store multiple converter in anything else than a list of object.
You can anyway try to cast the elements into what you need like it is done here (with a dictionary). Hirerate trough an heterogeneous and type-safe dictionary
No, you can't.
You have to make a Generic Method or Generic class like this:
void MyMethod<TInput, TOuput>()
{
List<Converter<TInput, TOuput>> myList = new List<Converter<TInput, TOuput>>();
}

Generic extension method refactor

I'm wondering if the following can be refactored in the way I would like it:
[EditorBrowsable(EditorBrowsableState.Never)]
public static class ListExtensions
{
public static PaginatedList<Y> ToMappedPaginatedList<T, Y>(this PaginatedList<T> source)
{
var mappedList = new List<Y>();
Mapper.Map(source, mappedList);
return new PaginatedList<Y>(mappedList, source.PageIndex, source.PageSize, source.TotalCount);
}
}
The Mapper.Map line is using AutoMapper to map properties from an entity to a DTO object.
This is called like this:
var list = await _service.GetAllAsync(pageIndex, _pageSize);
var dtoList = list.ToMappedPaginatedList<Farmer, FarmerDTO>();
but I'd like to call it like this:
var dtoList = list.ToMappedPaginatedList<FarmerDTO>();
This saves a little bit of typing and you don't always need to be aware of the source list its type. Unfortunately this code doesn't work and I'm not sure if there's a simple answer.
Anyone got an idea?
Thanks in advance.
Yannick
If you have access to the PaginatedList class, putting the method in there will enable the syntax you desire since the instance knows what it's own type is.
I don't recommend the following but it demonstrates a way to take advantage of type inference.
You can enable type inference by adding a 2nd "useless" parameter of type Y.
If you pass default(FarmerDTO) as the 2nd parameter, a null will be passed as the parameter value but the intended type will be inferred.
[EditorBrowsable(EditorBrowsableState.Never)]
public static class ListExtensions
{
public static PaginatedList<Y> ToMappedPaginatedList<T, Y>(this PaginatedList<T> source, Y destinationPlaceholder)
{
var mappedList = new List<Y>();
Mapper.Map(source, mappedList);
return new PaginatedList<Y>(mappedList, source.PageIndex, source.PageSize, source.TotalCount);
}
}
Call it like this:
var result1 = s.ToMappedPaginatedList(default(FarmerDTO));
Fair warning. I've never used this because I find the resulting code to be non-obvious as to what it is doing.
Either you call a method and specify all the generic arguments or you specify none and let the compiler infer them, there's no support for partial inference.
As such, the only way to get your code to compile is to make ToMappedPaginatedList take 1 generic parameter, instead of two.

C# simpler run time generics

Is there a way to invoke a generic function with a type known only at run time?
I'm trying to do something like:
static void bar()
{
object b = 6;
string c = foo<typeof(b)>();
}
static string foo<T>()
{
return typeof (T).Name;
}
Basically I want to decide on the type parameter only at run time, but the function I'm calling depends on the type parameter.
Also I know this can be done with reflections... but it's not the nicest solution to the problem...
I'm sort of looking for dynamic features in C#...
I'm writhing a bridge between two classes the first one is basically a big tree with different types of of objects (composite by interface) the other is a sort of a "super visitor".
the supper visitor accepts key-value dictioneries that map types to object it looks like:
dic.Add(object value)
and T is not necessarily the type of the value... a lot of times it isn't...
I know it's written poorly, but i can't fix it...
I can work around it, but only at runtime...
I already did it with reflections, but if there's a better way to do it without them i would be happy to learn...
Thank you
This is a bit of a hack but you can get dynamic to do the reflection work for you by something like,
class Program
{
static void Main(string[] args)
{
var b = 6;
var t = (dynamic)new T();
var n = t.Foo(b);
}
class T
{
public string Foo<T>(T a)
{
return typeof(T).Name;
}
}
}
Here the dynamic call will extract the type of b and use it as a type parameter for Foo().
You can use dynamic keyword if you're using .NET 4. In a word, the type of the variable will be resolved at run time so it is a super generic type ;) You can read a article here or read the MSDN documentation
Saly refelction is THE solution to the problem, whether it is nice or not is irrelevant here. It is the runtime designed mechanism to achieve exactly this. As there is no parameter or generics to use as input, this is the only way to do it - it is also senseless. As in: your example is bad. Because in the example the type is hardcoded.
If the method where b exists has b as generic parameter, the type is available for passing to foo. If not - reflection is THE way to go, albeit the syntax looks clumsy. Only one time, though.
This I believe is the only way:
var foo = typeof(Foo<>).MakeGenericType(typeof (bar));
You can set up a class which takes a type parameter at run time which can be used in the methods in that class.
public class GenericClass<T>()
{
ICommonInterface TheObject;
public GenericClass(T theObject)
{
TheObject = theObject;
}
public string GetName()
{
return TheObject.Name;
}
}
But this is only really useful if the Types being passed in share interfaces so have common properties between them. In your example it seems that relection is the answer as depending on the type you want to access specific properties.

How to dispatch C# generic method call into specialized method calls

I have the following C# class:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value ;
Parser.TryParse(p_value, out value);
// Do something with value
}
}
The point is to call the right Parser.TryParse method, depending on the generic type T.
This uses the following static class:
static public class Parser
{
static public void TryParse(string p_intput, out object p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out double p_output)
{
// Do something and return the right value
}
static public void TryParse(string p_intput, out int p_output)
{
// Do something and return the right value
}
}
I expected this to work: In the worst case, the "object" TryParse would be called. Instead, I have two compilation errors:
CS1502: The best overloaded method match for 'Parser.TryParse(string, out object)' has some invalid arguments
CS1503: Argument 2: cannot convert from 'out T' to 'out object'
Question 1: I don't understand why this doesn't work: I can be naive, but aren't all C# objects supposed to derive from "object" ? Why T cannot be converted to object?
Question 2: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T) ?
Note
The question was edited to reflect the original question intent (as written in the title: How to dispatch C# generic method call into specialized method calls)
Actually, ref and out parameters do not allow type variation. So, to pass a variable to a method expecting an out object parameter, that variable must be declared as object.
From the specification (§10.6.1.2 and §10.6.1.3)
When a formal parameter is a reference parameter, the corresponding argument in a method invocation must consist of the keyword ref followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
When a formal parameter is an output parameter, the corresponding argument in a method invocation must consist of the keyword out followed by a variable-reference (§5.3.3) of the same type as the formal parameter.
See: Why do ref and out parameters not allow type variation? for some insight into why.
Bonus question: How can I dispatch a method with generic type T into the right non-generic methods (i.e. MyType<T>.TryParse calling the right Parser.TryParse according to the right type of T)?
I'm going to turn it back around on you. Why are you doing this? If you are invoking MyType<T>.TryParse as, say, MyType<int>.TryParse, why not call Int32.TryParse directly? What is this extra layer buying you?
I know this is somewhat low-tech, but I have had the same problem, where I solved it by making a Dictionary<Type, Parser> containing the individual parsers. I will be interested in what answers this questions bring.
Regards,
Morten
Current solution
The current solution I use at work is based on dynamic dispatch, that is, the keyword dynamic as defined on C# 4.0.
The code is something like (from memory) :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// Because m_p is dynamic, the function to be called will
// be resolved at runtime, after T is known...
m_p.DoTryParse(p_input, out p_output) ;
}
// The dynamic keyword means every function called through
// m_p will be resolved at runtime, at the moment of the call
private dynamic m_p = new Parser() ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private void DoTryParse(string p_input, out double p_output)
{ /* Do something and return the right value */ }
private void DoTryParse(string p_input, out int p_output)
{ /* Do something and return the right value */ }
// etc.
private void DoTryParse<T>(string p_input, out T p_output)
{
// fallback method... There are no dedicated method for T,
// so p_output becomes the default value for T
p_output = default(T) ;
}
}
The elegant part is that it can't fail (the fallback function will be called, if none with a better signature match is found), and that it follows a simple pattern (overload the function).
Of course, the real-life, production code is somewhat different, and more complicated because, with but one public static method, I want to :
parse both reference objects (classes) and value objects (structs)
parse enums
parse nullable types
I want to offer the user the possibility to derive from Parser to offer its own overloads in addition to the default ones
But I guess the use of dynamic in the current solution is, in the end, the same thing as doing reflection as done in the original answer below. Only the "notation" changes.
Conclusion, I now have the following method :
public class Parser
{
static public void TryParse<T>(string p_input, out T p_output)
{
// etc.
}
}
which is able to parse anything, including in situations where T is not known at compile time (because the code is generic).
Original answer
Jason's answer was right about the first question (about the compiler errors). Still, I had no solution to my problem (dispatching from a generic method to non-generic methods according to the runtime generic type T).
I tried LukeH's answer, but it didn't work: The generic method is always called, no matter what (even when removing the out qualifier of the second parameter).
Morten's answer is the most sane one that should works, but it doesn't make use of reflection.
So, to solve my own problem, I used reflection. This needs the rewriting of the generic TryParse method:
public class MyType<T>
{
public void TryParse(string p_value)
{
T value = default(T);
// search for the method using reflection
System.Reflection.MethodInfo methodInfo = typeof(Parser).GetMethod
(
"TryParse",
new System.Type[] { typeof(string), typeof(T).MakeByRefType() }
);
if (methodInfo != null)
{
// the method does exist, so we can now call it
var parameters = new object[] { p_value, value };
methodInfo.Invoke(null, parameters);
value = (T)parameters[1];
}
else
{
// The method does not exist. Handle that case
}
}
}
I have the source code available if needed.
This problem intrigued me, so I did some research and found a nice thing by Paul Madox. This seems to do the trick.
public static T SafeParseAndAssign<T>(string val) where T: new()
{
try
{
T ValOut = new T();
MethodInfo MI = ValOut.GetType().
GetMethod("Parse", new Type[] { val.GetType() });
return (T)MI.Invoke(ValOut, new object[] { val });
}
catch
{
// swallow exception
}
return default(T);
}

C#: Dynamic runtime cast

I would like to implement a method with the following signature
dynamic Cast(object obj, Type castTo);
Anyone know how to do that? obj definitely implements castTo but needs to be cast properly in order to have some of my app's runtime binding stuff work out.
Edit: If some of the answers don't make sense it's because I initially accidentally typed dynamic Cast(dynamic obj, Type castTo); - I mean the input should be object or some other guaranteed base class
I think you're confusing the issues of casting and converting here.
Casting: The act of changing the type of a reference which points to an object. Either moving up or down the object hierarchy or to an implemented interface
Converting: Creating a new object from the original source object of a different type and accessing it through a reference to that type.
It's often hard to know the difference between the 2 in C# because both of them use the same C# operator: the cast.
In this situation you are almost certainly not looking for a cast operation. Casting a dynamic to another dynamic is essentially an identity conversion. It provides no value because you're just getting a dynamic reference back to the same underlying object. The resulting lookup would be no different.
Instead what you appear to want in this scenario is a conversion. That is morphing the underlying object to a different type and accessing the resulting object in a dynamic fashion. The best API for this is Convert.ChangeType.
public static dynamic Convert(dynamic source, Type dest) {
return Convert.ChangeType(source, dest);
}
EDIT
The updated question has the following line:
obj definitely implements castTo
If this is the case then the Cast method doesn't need to exist. The source object can simply be assigned to a dynamic reference.
dynamic d = source;
It sounds like what you're trying to accomplish is to see a particular interface or type in the hierarchy of source through a dynamic reference. That is simply not possible. The resulting dynamic reference will see the implementation object directly. It doesn't look through any particular type in the hierarchy of source. So the idea of casting to a different type in the hierarchy and then back to dynamic is exactly identical to just assigning to dynamic in the first place. It will still point to the same underlying object.
This should work:
public static dynamic Cast(dynamic obj, Type castTo)
{
return Convert.ChangeType(obj, castTo);
}
Edit
I've written the following test code:
var x = "123";
var y = Cast(x, typeof(int));
var z = y + 7;
var w = Cast(z, typeof(string)); // w == "130"
It does resemble the kind of "typecasting" one finds in languages like PHP, JavaScript or Python (because it also converts the value to the desired type). I don't know if that's a good thing, but it certainly works... :-)
I realize this has been answered, but I used a different approach and thought it might be worth sharing. Also, I feel like my approach might produce unwanted overhead. However, I'm not able to observer or calculate anything happening that is that bad under the loads we observe. I was looking for any useful feedback on this approach.
The problem with working with dynamics is that you can't attach any functions to the dynamic object directly. You have to use something that can figure out the assignments that you don't want to figure out every time.
When planning this simple solution, I looked at what the valid intermediaries are when attempting to retype similar objects. I found that a binary array, string (xml, json) or hard coding a conversion (IConvertable) were the usual approaches. I don't want to get into binary conversions due to a code maintainability factor and laziness.
My theory was that Newtonsoft could do this by using a string intermediary.
As a downside, I am fairly certain that when converting the string to an object, that it would use reflection by searching the current assembly for an object with matching properties, create the type, then instantiate the properties, which would require more reflection. If true, all of this can be considered avoidable overhead.
C#:
//This lives in a helper class
public static ConvertDynamic<T>(dynamic data)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(data));
}
//Same helper, but in an extension class (public static class),
//but could be in a base class also.
public static ToModelList<T>(this List<dynamic> list)
{
List<T> retList = new List<T>();
foreach(dynamic d in list)
{
retList.Add(ConvertDynamic<T>(d));
}
}
With that said, this fits another utility I've put together that lets me make any object into a dynamic. I know I had to use reflection to do that correctly:
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
return expando as ExpandoObject;
}
I had to offer that function. An arbitrary object assigned to a dynamic typed variable cannot be converted to an IDictionary, and will break the ConvertDynamic function. For this function chain to be used it has to be provided a dynamic of System.Dynamic.ExpandoObject, or IDictionary<string, object>.
Best I got so far:
dynamic DynamicCast(object entity, Type to)
{
var openCast = this.GetType().GetMethod("Cast", BindingFlags.Static | BindingFlags.NonPublic);
var closeCast = openCast.MakeGenericMethod(to);
return closeCast.Invoke(entity, new[] { entity });
}
static T Cast<T>(object entity) where T : class
{
return entity as T;
}
The opensource framework Dynamitey has a static method that does late binding using DLR including cast conversion among others.
dynamic Cast(object obj, Type castTo){
return Dynamic.InvokeConvert(obj, castTo, explict:true);
}
The advantage of this over a Cast<T> called using reflection, is that this will also work for any IDynamicMetaObjectProvider that has dynamic conversion operators, ie. TryConvert on DynamicObject.
Try a generic:
public static T CastTo<T>(this dynamic obj, bool safeCast) where T:class
{
try
{
return (T)obj;
}
catch
{
if(safeCast) return null;
else throw;
}
}
This is in extension method format, so its usage would be as if it were a member of dynamic objects:
dynamic myDynamic = new Something();
var typedObject = myDynamic.CastTo<Something>(false);
EDIT: Grr, didn't see that. Yes, you could reflectively close the generic, and it wouldn't be hard to hide in a non-generic extension method:
public static dynamic DynamicCastTo(this dynamic obj, Type castTo, bool safeCast)
{
MethodInfo castMethod = this.GetType().GetMethod("CastTo").MakeGenericMethod(castTo);
return castMethod.Invoke(null, new object[] { obj, safeCast });
}
I'm just not sure what you'd get out of this. Basically you're taking a dynamic, forcing a cast to a reflected type, then stuffing it back in a dynamic. Maybe you're right, I shouldn't ask. But, this'll probably do what you want. Basically when you go into dynamic-land, you lose the need to perform most casting operations as you can discover what an object is and does through reflective methods or trial and error, so there aren't many elegant ways to do this.
Slight modification on #JRodd version to support objects coming from Json (JObject)
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
//Get the type of object
Type t = value.GetType();
//If is Dynamic Expando object
if (t.Equals(typeof(ExpandoObject)))
{
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
}
//If coming from Json object
else if (t.Equals(typeof(JObject)))
{
foreach (JProperty property in (JToken)value)
expando.Add(property.Name, property.Value);
}
else //Try converting a regular object
{
string str = JsonConvert.SerializeObject(value);
ExpandoObject obj = JsonConvert.DeserializeObject<ExpandoObject>(str);
return obj;
}
return expando as ExpandoObject;
}
You can use the expression pipeline to achieve this:
public static Func<object, object> Caster(Type type)
{
var inputObject = Expression.Parameter(typeof(object));
return Expression.Lambda<Func<object,object>>(Expression.Convert(inputObject, type), inputPara).Compile();
}
which you can invoke like:
object objAsDesiredType = Caster(desiredType)(obj);
Drawbacks: The compilation of this lambda is slower than nearly all other methods mentioned already
Advantages: You can cache the lambda, then this should be actually the fastest method, it is identical to handwritten code at compile time
Alternatively:
public static T Cast<T>(this dynamic obj) where T:class
{
return obj as T;
}

Categories